diff -Naur gcc-4.4-2009q3/boehm-gc/include/private/gc_locks.h gcc-4.4-2010q1/boehm-gc/include/private/gc_locks.h
--- a/src/boehm-gc/include/private/gc_locks.h	2009-10-12 21:22:29.000000000 +0300
+++ b/src/boehm-gc/include/private/gc_locks.h	2010-03-30 10:40:39.000000000 +0300
@@ -139,49 +139,35 @@
 #      define GC_TEST_AND_SET_DEFINED
 #    endif
 #    if defined(POWERPC)
-#     if 0 /* CPP_WORDSZ == 64  totally broken to use int locks with ldarx */
-        inline static int GC_test_and_set(volatile unsigned int *addr) {
-          unsigned long oldval;
-          unsigned long temp = 1; /* locked value */
-
-          __asm__ __volatile__(
-               "1:\tldarx %0,0,%3\n"   /* load and reserve               */
-               "\tcmpdi %0, 0\n"       /* if load is                     */
-               "\tbne 2f\n"            /*   non-zero, return already set */
-               "\tstdcx. %2,0,%1\n"    /* else store conditional         */
-               "\tbne- 1b\n"           /* retry if lost reservation      */
-               "\tsync\n"              /* import barrier                 */
-               "2:\t\n"                /* oldval is zero if we set       */
-              : "=&r"(oldval), "=p"(addr)
-              : "r"(temp), "1"(addr)
-              : "cr0","memory");
-          return (int)oldval;
-        }
+#     define GC_TEST_AND_SET_DEFINED
+#     define GC_CLEAR_DEFINED
+#     if (__GNUC__>4)||((__GNUC__==4)&&(__GNUC_MINOR__>=4))
+#       define GC_test_and_set(addr) __sync_lock_test_and_set (addr, 1)
+#       define GC_clear(addr) __sync_lock_release (addr)
 #     else
         inline static int GC_test_and_set(volatile unsigned int *addr) {
           int oldval;
           int temp = 1; /* locked value */
 
           __asm__ __volatile__(
-               "1:\tlwarx %0,0,%3\n"   /* load and reserve               */
+               "\n1:\n"
+	       "\tlwarx %0,%y3\n"      /* load and reserve, 32-bits      */
                "\tcmpwi %0, 0\n"       /* if load is                     */
                "\tbne 2f\n"            /*   non-zero, return already set */
-               "\tstwcx. %2,0,%1\n"    /* else store conditional         */
+               "\tstwcx. %2,%y3\n"     /* else store conditional         */
                "\tbne- 1b\n"           /* retry if lost reservation      */
                "\tsync\n"              /* import barrier                 */
                "2:\t\n"                /* oldval is zero if we set       */
-              : "=&r"(oldval), "=p"(addr)
-              : "r"(temp), "1"(addr)
+              : "=&r"(oldval), "=m"(addr)
+              : "r"(temp), "Z"(addr)
               : "cr0","memory");
           return oldval;
         }
-#     endif
-#     define GC_TEST_AND_SET_DEFINED
       inline static void GC_clear(volatile unsigned int *addr) {
 	__asm__ __volatile__("lwsync" : : : "memory");
         *(addr) = 0;
       }
-#     define GC_CLEAR_DEFINED
+#    endif
 #    endif
 #    if defined(ALPHA) 
         inline static int GC_test_and_set(volatile unsigned int * addr)
diff -Naur a/src/configure b/src/configure
--- a/src/configure	2009-10-12 21:26:07.000000000 +0300
+++ b/src/configure	2010-03-30 10:42:22.000000000 +0300
@@ -2338,10 +2338,17 @@
     esac
     libgloss_dir=arm
     ;;
+  arm*-*-nucleuseabi)
+    noconfigdirs="$noconfigdirs ${libgcj}"
+    libgloss_dir=arm
+    ;;
   arm*-*-symbianelf*)
     noconfigdirs="$noconfigdirs ${libgcj} target-libiberty"
     libgloss_dir=arm
     ;;
+  arm*-*-mingw32*)
+    noconfigdirs="$noconfigdirs target-libgloss ${libgcj} target-libiberty"
+    ;;
   arm-*-pe*)
     noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
     ;;
diff -Naur a/src/configure.ac b/src/configure.ac
--- a/src/configure.ac	2009-10-12 21:26:07.000000000 +0300
+++ b/src/configure.ac	2010-03-30 10:42:22.000000000 +0300
@@ -573,10 +573,17 @@
     esac
     libgloss_dir=arm
     ;;
+  arm*-*-nucleuseabi)
+    noconfigdirs="$noconfigdirs ${libgcj}"
+    libgloss_dir=arm
+    ;;
   arm*-*-symbianelf*)
     noconfigdirs="$noconfigdirs ${libgcj} target-libiberty"
     libgloss_dir=arm
     ;;
+  arm*-*-mingw32*)
+    noconfigdirs="$noconfigdirs target-libgloss ${libgcj} target-libiberty"
+    ;;
   arm-*-pe*)
     noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
     ;;
diff -Naur a/src/fixincludes/fixincl.x b/src/fixincludes/fixincl.x
--- a/src/fixincludes/fixincl.x	2009-10-12 21:26:06.000000000 +0300
+++ b/src/fixincludes/fixincl.x	2010-03-30 10:42:22.000000000 +0300
@@ -2,11 +2,11 @@
  * 
  * DO NOT EDIT THIS FILE   (fixincl.x)
  * 
- * It has been AutoGen-ed  Monday July 20, 2009 at 01:53:53 PM PDT
+ * It has been AutoGen-ed  Wednesday March 24, 2010 at 04:28:54 PM PDT
  * From the definitions    inclhack.def
  * and the template file   fixincl
  */
-/* DO NOT SVN-MERGE THIS FILE, EITHER Mon Jul 20 13:53:53 PDT 2009
+/* DO NOT SVN-MERGE THIS FILE, EITHER Wed Mar 24 16:28:54 PDT 2010
  *
  * You must regenerate it.  Use the ./genfixes script.
  *
@@ -15,7 +15,7 @@
  * certain ANSI-incompatible system header files which are fixed to work
  * correctly with ANSI C and placed in a directory that GNU C will search.
  *
- * This file contains 181 fixup descriptions.
+ * This file contains 182 fixup descriptions.
  *
  * See README for more information.
  *
@@ -2336,6 +2336,45 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * *
  *
+ *  Description of Glibc_Strncpy fix
+ */
+tSCC zGlibc_StrncpyName[] =
+     "glibc_strncpy";
+
+/*
+ *  File name selection pattern
+ */
+tSCC zGlibc_StrncpyList[] =
+  "bits/string2.h\0";
+/*
+ *  Machine/OS name selection pattern
+ */
+#define apzGlibc_StrncpyMachs (const char**)NULL
+
+/*
+ *  content bypass pattern - skip fix if pattern found
+ */
+tSCC zGlibc_StrncpyBypass0[] =
+       "__builtin_strncpy";
+
+#define    GLIBC_STRNCPY_TEST_CT  1
+static tTestDesc aGlibc_StrncpyTests[] = {
+  { TT_NEGREP,   zGlibc_StrncpyBypass0, (regex_t*)NULL }, };
+
+/*
+ *  Fix Command Arguments for Glibc_Strncpy
+ */
+static const char* apzGlibc_StrncpyPatch[] = {
+    "format",
+    "#  define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)",
+    "#  define strncpy([^\n\
+]*\\\\\n\
+)*[^\n\
+]*",
+    (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
  *  Description of Gnu_Types fix
  */
 tSCC zGnu_TypesName[] =
@@ -7363,9 +7402,9 @@
  *
  *  List of all fixes
  */
-#define REGEX_COUNT          227
+#define REGEX_COUNT          228
 #define MACH_LIST_SIZE_LIMIT 169
-#define FIX_COUNT            181
+#define FIX_COUNT            182
 
 /*
  *  Enumerate the fixes
@@ -7427,6 +7466,7 @@
     GLIBC_C99_INLINE_4_FIXIDX,
     GLIBC_MUTEX_INIT_FIXIDX,
     GLIBC_STRING2_MEMSET_FIXIDX,
+    GLIBC_STRNCPY_FIXIDX,
     GNU_TYPES_FIXIDX,
     HP_INLINE_FIXIDX,
     HP_SYSFILE_FIXIDX,
@@ -7835,6 +7875,11 @@
      GLIBC_STRING2_MEMSET_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
      aGlibc_String2_MemsetTests,   apzGlibc_String2_MemsetPatch, 0 },
 
+  {  zGlibc_StrncpyName,    zGlibc_StrncpyList,
+     apzGlibc_StrncpyMachs,
+     GLIBC_STRNCPY_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+     aGlibc_StrncpyTests,   apzGlibc_StrncpyPatch, 0 },
+
   {  zGnu_TypesName,    zGnu_TypesList,
      apzGnu_TypesMachs,
      GNU_TYPES_TEST_CT, FD_MACH_IFNOT | FD_SUBROUTINE,
diff -Naur a/src/fixincludes/inclhack.def b/src/fixincludes/inclhack.def
--- a/src/fixincludes/inclhack.def	2009-10-12 21:26:06.000000000 +0300
+++ b/src/fixincludes/inclhack.def	2010-03-30 10:42:22.000000000 +0300
@@ -1317,6 +1317,28 @@
 };
 
 
+/* Some versions of glibc have a version of bits/string2.h that
+   produces "value computed is not used" warnings from strncpy; fix
+   this definition by using __builtin_strncpy instead as in newer
+   versions.  */
+fix = {
+    hackname  = glibc_strncpy;
+    files     = bits/string2.h;
+    bypass    = "__builtin_strncpy";
+    c_fix     = format;
+    c_fix_arg = "#  define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)";
+    c_fix_arg = "#  define strncpy([^\n]*\\\\\n)*[^\n]*";
+    test_text = <<-EOT
+	#  define strncpy(dest, src, n) \
+	  (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n)      \\
+			  ? (strlen (src) + 1 >= ((size_t) (n))			      \\
+			     ? (char *) memcpy (dest, src, n)			      \\
+			     : strncpy (dest, src, n))				      \\
+			  : strncpy (dest, src, n)))
+	EOT;
+
+};
+
 /*
  * Fix these files to use the types we think they should for
  * ptrdiff_t, size_t, and wchar_t.
diff -Naur a/src/fixincludes/tests/base/bits/string2.h b/src/fixincludes/tests/base/bits/string2.h
--- a/src/fixincludes/tests/base/bits/string2.h	2009-10-12 21:26:06.000000000 +0300
+++ b/src/fixincludes/tests/base/bits/string2.h	2010-03-30 10:42:22.000000000 +0300
@@ -25,3 +25,8 @@
 #endif
 
 #endif  /* GLIBC_STRING2_MEMSET_CHECK */
+
+
+#if defined( GLIBC_STRNCPY_CHECK )
+#  define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)
+#endif  /* GLIBC_STRNCPY_CHECK */
diff -Naur a/src/gcc/ada/gcc-interface/Make-lang.in b/src/gcc/ada/gcc-interface/Make-lang.in
--- a/src/gcc/ada/gcc-interface/Make-lang.in	2009-10-12 21:20:20.000000000 +0300
+++ b/src/gcc/ada/gcc-interface/Make-lang.in	2010-03-30 10:38:41.000000000 +0300
@@ -23,7 +23,7 @@
 #
 # foo.all.cross, foo.start.encap, foo.rest.encap,
 # foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
-# foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
 # foo.mostlyclean, foo.clean, foo.distclean,
 # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
 #
@@ -450,6 +450,8 @@
 
 ada.html:
 
+ada.install-html:
+
 doc/gnat_ugn.dvi: doc/gnat_ugn.texi $(gcc_docdir)/include/fdl.texi	\
 	$(gcc_docdir)/include/gcc-common.texi gcc-vers.texi
 	$(TEXI2DVI) -c -I $(abs_docdir)/include -o $@ $<
diff -Naur a/src/gcc/basic-block.h b/src/gcc/basic-block.h
--- a/src/gcc/basic-block.h	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/basic-block.h	2010-04-14 10:28:39.000000000 +0300
@@ -900,6 +900,10 @@
 
 /* In cfgcleanup.c.  */
 extern bool cleanup_cfg (int);
+extern int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *);
+extern int flow_find_head_matching_sequence (int, basic_block, basic_block,
+					     rtx *, rtx *, int);
+
 extern bool delete_unreachable_blocks (void);
 
 extern bool mark_dfs_back_edges (void);
diff -Naur a/src/gcc/caller-save.c b/src/gcc/caller-save.c
--- a/src/gcc/caller-save.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/caller-save.c	2010-04-02 10:28:17.000000000 +0300
@@ -40,6 +40,9 @@
 #include "df.h"
 #include "ggc.h"
 
+/* True if caller-save has been initialized.  */
+bool caller_save_initialized_p;
+
 /* Call used hard registers which can not be saved because there is no
    insn for this.  */
 HARD_REG_SET no_caller_save_reg_set;
@@ -204,6 +207,11 @@
   rtx address;
   int i, j;
 
+  if (caller_save_initialized_p)
+    return;
+
+  caller_save_initialized_p = true;
+
   CLEAR_HARD_REG_SET (no_caller_save_reg_set);
   /* First find all the registers that we need to deal with and all
      the modes that they can have.  If we can't find a mode to use,
diff -Naur a/src/gcc/calls.c b/src/gcc/calls.c
--- a/src/gcc/calls.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/calls.c	2010-03-30 10:39:47.000000000 +0300
@@ -711,7 +711,9 @@
 
 	   For small register classes, also do this if this call uses
 	   register parameters.  This is to avoid reload conflicts while
-	   loading the parameters registers.  */
+	   loading the parameters registers.
+	   
+	   Avoid creating the extra move if optimizing for size.  */
 
 	else if ((! (REG_P (args[i].value)
 		     || (GET_CODE (args[i].value) == SUBREG
@@ -719,6 +721,7 @@
 		 && args[i].mode != BLKmode
 		 && rtx_cost (args[i].value, SET, optimize_insn_for_speed_p ())
 		    > COSTS_N_INSNS (1)
+		 && !optimize_size
 		 && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
 		     || optimize))
 	  args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
diff -Naur a/src/gcc/cfgcleanup.c b/src/gcc/cfgcleanup.c
--- a/src/gcc/cfgcleanup.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/cfgcleanup.c	2010-04-14 10:28:39.000000000 +0300
@@ -68,7 +68,6 @@
 static bool try_crossjump_to_edge (int, edge, edge);
 static bool try_crossjump_bb (int, basic_block);
 static bool outgoing_edges_match (int, basic_block, basic_block);
-static int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *);
 static bool old_insns_match_p (int, rtx, rtx);
 
 static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block);
@@ -967,13 +966,27 @@
      be filled that clobbers a parameter expected by the subroutine.
 
      ??? We take the simple route for now and assume that if they're
-     equal, they were constructed identically.  */
+     equal, they were constructed identically.
 
-  if (CALL_P (i1)
-      && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
+     Also check for identical exception regions.  */
+
+  if (CALL_P (i1))
+    {
+      /* Ensure the same EH region.  */
+      rtx n1 = find_reg_note (i1, REG_EH_REGION, 0);
+      rtx n2 = find_reg_note (i2, REG_EH_REGION, 0);
+
+      if (!n1 && n2)
+	return false;
+
+      if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0)))
+	return false;
+
+      if (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
 			CALL_INSN_FUNCTION_USAGE (i2))
-	  || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
-    return false;
+	  || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2))
+	return false;
+    }
 
 #ifdef STACK_REGS
   /* If cross_jump_death_matters is not 0, the insn's mode
@@ -1053,7 +1066,7 @@
    To simplify callers of this function, if the blocks match exactly,
    store the head of the blocks in *F1 and *F2.  */
 
-static int
+int
 flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
 		      basic_block bb2, rtx *f1, rtx *f2)
 {
@@ -1159,6 +1172,108 @@
   return ninsns;
 }
 
+/* Like flow_find_cross_jump, except start looking for a matching sequence from
+   the head of the two blocks.  Do not include jumps at the end.
+   If STOP_AFTER is nonzero, stop after finding that many matching
+   instructions.  */
+
+int
+flow_find_head_matching_sequence (int mode ATTRIBUTE_UNUSED, basic_block bb1,
+				  basic_block bb2, rtx *f1, rtx *f2,
+				  int stop_after)
+{
+  rtx i1, i2, last1, last2, beforelast1, beforelast2;
+  int ninsns = 0;
+  edge e;
+  edge_iterator ei;
+  int nehedges1 = 0, nehedges2 = 0;
+
+  FOR_EACH_EDGE (e, ei, bb1->succs)
+    if (e->flags & EDGE_EH)
+      nehedges1++;
+  FOR_EACH_EDGE (e, ei, bb2->succs)
+    if (e->flags & EDGE_EH)
+      nehedges2++;
+
+  i1 = BB_HEAD (bb1);
+  i2 = BB_HEAD (bb2);
+  last1 = beforelast1 = last2 = beforelast2 = NULL_RTX;
+
+  while (true)
+    {
+
+      /* Ignore notes.  */
+      while (!INSN_P (i1) && i1 != BB_END (bb1))
+	i1 = NEXT_INSN (i1);
+
+      while (!INSN_P (i2) && i2 != BB_END (bb2))
+	i2 = NEXT_INSN (i2);
+
+      if (NOTE_P (i1) || NOTE_P (i2)
+	  || JUMP_P (i1) || JUMP_P (i2))
+	break;
+
+      if ((i1 == BB_END (bb1) && i2 != BB_END (bb2)
+	   && nehedges1 > 0)
+	  || (i2 == BB_END (bb2) && i1 != BB_END (bb1)
+	      && nehedges2 > 0)
+	  || (i1 == BB_END (bb1) && i2 == BB_END (bb2)
+	      && nehedges1 != nehedges2))
+	break;
+
+      if (!old_insns_match_p (mode, i1, i2))
+	break;
+
+      merge_memattrs (i1, i2);
+
+      /* Don't begin a cross-jump with a NOTE insn.  */
+      if (INSN_P (i1))
+	{
+	  /* If the merged insns have different REG_EQUAL notes, then
+	     remove them.  */
+	  rtx equiv1 = find_reg_equal_equiv_note (i1);
+	  rtx equiv2 = find_reg_equal_equiv_note (i2);
+
+	  if (equiv1 && !equiv2)
+	    remove_note (i1, equiv1);
+	  else if (!equiv1 && equiv2)
+	    remove_note (i2, equiv2);
+	  else if (equiv1 && equiv2
+		   && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))
+	    {
+	      remove_note (i1, equiv1);
+	      remove_note (i2, equiv2);
+	    }
+
+	  beforelast1 = last1, beforelast2 = last2;
+	  last1 = i1, last2 = i2;
+	  ninsns++;
+	}
+
+      if (i1 == BB_END (bb1) || i2 == BB_END (bb2)
+	  || (stop_after > 0 && ninsns == stop_after))
+	break;
+
+      i1 = NEXT_INSN (i1);
+      i2 = NEXT_INSN (i2);
+    }
+
+#ifdef HAVE_cc0
+  /* Don't allow a compare to be shared by cross-jumping unless the insn
+     after the compare is also shared.  */
+  if (ninsns && reg_mentioned_p (cc0_rtx, last1) && sets_cc0_p (last1))
+    last1 = beforelast1, last2 = beforelast2, ninsns--;
+#endif
+
+  if (ninsns)
+    {
+      *f1 = last1;
+      *f2 = last2;
+    }
+
+  return ninsns;
+}
+
 /* Return true iff outgoing edges of BB1 and BB2 match, together with
    the branch instruction.  This means that if we commonize the control
    flow before end of the basic block, the semantic remains unchanged.
diff -Naur a/src/gcc/cgraphunit.c b/src/gcc/cgraphunit.c
--- a/src/gcc/cgraphunit.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/cgraphunit.c	2010-03-30 10:39:47.000000000 +0300
@@ -1293,6 +1293,7 @@
   timevar_pop (TV_CGRAPHOPT);
 
   /* Output everything.  */
+  (*debug_hooks->assembly_start) ();
   if (!quiet_flag)
     fprintf (stderr, "Assembling functions:\n");
 #ifdef ENABLE_CHECKING
diff -Naur a/src/gcc/config/arm/aout.h b/src/gcc/config/arm/aout.h
--- a/src/gcc/config/arm/aout.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/aout.h	2010-04-10 10:19:15.000000000 +0300
@@ -163,31 +163,45 @@
   {"mvdx12", 39},				\
   {"mvdx13", 40},				\
   {"mvdx14", 41},				\
-  {"mvdx15", 42},				\
-  {"d0", 63}, {"q0", 63},			\
-  {"d1", 65},					\
-  {"d2", 67}, {"q1", 67},			\
-  {"d3", 69},					\
-  {"d4", 71}, {"q2", 71},			\
-  {"d5", 73},					\
-  {"d6", 75}, {"q3", 75},			\
-  {"d7", 77},					\
-  {"d8", 79}, {"q4", 79},			\
-  {"d9", 81},					\
-  {"d10", 83}, {"q5", 83},			\
-  {"d11", 85},					\
-  {"d12", 87}, {"q6", 87},			\
-  {"d13", 89},					\
-  {"d14", 91}, {"q7", 91},			\
-  {"d15", 93},					\
-  {"q8", 95},					\
-  {"q9", 99},					\
-  {"q10", 103},					\
-  {"q11", 107},					\
-  {"q12", 111},					\
-  {"q13", 115},					\
-  {"q14", 119},					\
-  {"q15", 123}					\
+  {"mvdx15", 42}				\
+}
+#endif
+
+#ifndef OVERLAPPING_REGISTER_NAMES
+#define OVERLAPPING_REGISTER_NAMES		\
+{						\
+  {"d0", 63, 2},				\
+  {"d1", 65, 2},				\
+  {"d2", 67, 2},				\
+  {"d3", 69, 2},				\
+  {"d4", 71, 2},				\
+  {"d5", 73, 2},				\
+  {"d6", 75, 2},				\
+  {"d7", 77, 2},				\
+  {"d8", 79, 2},				\
+  {"d9", 81, 2},				\
+  {"d10", 83, 2},				\
+  {"d11", 85, 2},				\
+  {"d12", 87, 2},				\
+  {"d13", 89, 2},				\
+  {"d14", 91, 2},				\
+  {"d15", 93, 2},				\
+  {"q0", 63, 4},				\
+  {"q1", 67, 4},				\
+  {"q2", 71, 4},				\
+  {"q3", 75, 4},				\
+  {"q4", 79, 4},				\
+  {"q5", 83, 4},				\
+  {"q6", 87, 4},				\
+  {"q7", 91, 4},				\
+  {"q8", 95, 4},				\
+  {"q9", 99, 4},				\
+  {"q10", 103, 4},				\
+  {"q11", 107, 4},				\
+  {"q12", 111, 4},				\
+  {"q13", 115, 4},				\
+  {"q14", 119, 4},				\
+  {"q15", 123, 4}				\
 }
 #endif
 
diff -Naur a/src/gcc/config/arm/arm.c b/src/gcc/config/arm/arm.c
--- a/src/gcc/config/arm/arm.c	2009-10-14 21:55:23.000000000 +0300
+++ b/src/gcc/config/arm/arm.c	2010-04-13 10:45:12.000000000 +0300
@@ -136,6 +136,7 @@
 				 tree);
 static bool arm_rtx_costs_1 (rtx, enum rtx_code, int*, bool);
 static bool arm_size_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *);
+static bool thumb2_size_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *);
 static bool arm_slowmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
 static bool arm_fastmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
 static bool arm_xscale_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
@@ -239,6 +240,17 @@
 #undef  TARGET_ASM_INTEGER
 #define TARGET_ASM_INTEGER arm_assemble_integer
 
+#ifdef ARM_PE
+#undef  TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.2byte\t"
+#undef  TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.4byte\t"
+#undef  TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP "\t.8byte\t"
+#undef  TARGET_ASM_UNALIGNED_TI_OP
+#define TARGET_ASM_UNALIGNED_TI_OP NULL
+#endif
+
 #undef  TARGET_ASM_FUNCTION_PROLOGUE
 #define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
 
@@ -755,7 +767,7 @@
   {"armv7-a", cortexa8,	  "7A",	 FL_CO_PROC |		  FL_FOR_ARCH7A, NULL},
   {"armv7-r", cortexr4,	  "7R",	 FL_CO_PROC |		  FL_FOR_ARCH7R, NULL},
   {"armv7-m", cortexm3,	  "7M",	 FL_CO_PROC |		  FL_FOR_ARCH7M, NULL},
-  {"armv7e-m",   cortexm3, "7EM", FL_CO_PROC |		  FL_FOR_ARCH7EM, NULL},
+  {"armv7e-m", cortexm4,  "7EM", FL_CO_PROC |		  FL_FOR_ARCH7EM, NULL},
   {"ep9312",  ep9312,     "4T",  FL_LDSCHED | FL_CIRRUS | FL_FOR_ARCH4, NULL},
   {"iwmmxt",  iwmmxt,     "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL},
   {"iwmmxt2", iwmmxt2,     "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL},
@@ -1019,12 +1031,12 @@
       /* Conversions.  */
       set_conv_libfunc (trunc_optab, HFmode, SFmode,
 			(arm_fp16_format == ARM_FP16_FORMAT_IEEE
-			 ? "__gnu_f2h_ieee"
-			 : "__gnu_f2h_alternative"));
+			 ? "__aeabi_f2h"
+			 : "__aeabi_f2h_alt"));
       set_conv_libfunc (sext_optab, SFmode, HFmode, 
 			(arm_fp16_format == ARM_FP16_FORMAT_IEEE
-			 ? "__gnu_h2f_ieee"
-			 : "__gnu_h2f_alternative"));
+			 ? "__aeabi_h2f"
+			 : "__aeabi_h2f_alt"));
       
       /* Arithmetic.  */
       set_optab_libfunc (add_optab, HFmode, NULL);
@@ -3048,13 +3060,82 @@
    immediate value easier to load.  */
 
 enum rtx_code
-arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
-			     rtx * op1)
+arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
 {
-  unsigned HOST_WIDE_INT i = INTVAL (*op1);
-  unsigned HOST_WIDE_INT maxval;
+  enum machine_mode mode;
+  unsigned HOST_WIDE_INT i, maxval;
+
+  mode = GET_MODE (*op0);
+  if (mode == VOIDmode)
+    mode = GET_MODE (*op1);
+
   maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1;
 
+  /* For DImode, we have GE/LT/GEU/LTU comparisons.  In ARM mode
+     we can also use cmp/cmpeq for GTU/LEU.  GT/LE must be either
+     reversed or (for constant OP1) adjusted to GE/LT.  Similarly
+     for GTU/LEU in Thumb mode.  */
+  if (mode == DImode)
+    {
+      rtx tem;
+
+      /* To keep things simple, always use the Cirrus cfcmp64 if it is
+	 available.  */
+      if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK)
+	return code;
+
+      if (code == GT || code == LE
+	  || (!TARGET_ARM && (code == GTU || code == LEU)))
+	{
+	  /* Missing comparison.  First try to use an available
+	     comparison.  */
+	  if (GET_CODE (*op1) == CONST_INT)
+	    {
+	      i = INTVAL (*op1);
+	      switch (code)
+		{
+		case GT:
+		case LE:
+		  if (i != maxval
+		      && arm_const_double_by_immediates (GEN_INT (i + 1)))
+		    {
+		      *op1 = GEN_INT (i + 1);
+		      return code == GT ? GE : LT;
+		    }
+		  break;
+		case GTU:
+		case LEU:
+		  if (i != ~((unsigned HOST_WIDE_INT) 0)
+		      && arm_const_double_by_immediates (GEN_INT (i + 1)))
+		    {
+		      *op1 = GEN_INT (i + 1);
+		      return code == GTU ? GEU : LTU;
+		    }
+		  break;
+		default:
+		  gcc_unreachable ();
+		}
+	    }
+
+	  /* If that did not work, reverse the condition.  */
+	  tem = *op0;
+	  *op0 = *op1;
+	  *op1 = tem;
+	  return swap_condition (code);
+	}
+
+      return code;
+    }
+
+  /* Comparisons smaller than DImode.  Only adjust comparisons against
+     an out-of-range constant.  */
+  if (GET_CODE (*op1) != CONST_INT
+      || const_ok_for_arm (INTVAL (*op1))
+      || const_ok_for_arm (- INTVAL (*op1)))
+    return code;
+
+  i = INTVAL (*op1);
+
   switch (code)
     {
     case EQ:
@@ -3165,6 +3246,27 @@
 			  convert_optab_libfunc (sext_optab, SFmode, HFmode)))
 	return gen_rtx_REG (mode, ARG_REGISTER(1));
 
+      /* Values from double-precision helper functions are returned in core
+	 registers if the selected core only supports single-precision
+	 arithmetic, even if we are using the hard-float ABI.  */
+      if (TARGET_VFP
+	  && (rtx_equal_p (libcall, optab_libfunc (add_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (sdiv_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (smul_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (neg_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (sub_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (eq_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (lt_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (le_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (ge_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (gt_optab, DFmode))
+	      || rtx_equal_p (libcall, optab_libfunc (unord_optab, DFmode))
+	      || rtx_equal_p (libcall, convert_optab_libfunc (sext_optab,
+							      DFmode, SFmode))
+	      || rtx_equal_p (libcall, convert_optab_libfunc (trunc_optab,
+							      SFmode, DFmode))))
+        return gen_rtx_REG (mode, ARG_REGISTER (1));
+
       /* XXX There are other libcalls that return in integer registers,
 	 but I think they are all handled by hard insns.  */
     }
@@ -4114,6 +4216,31 @@
 			  convert_optab_libfunc (sext_optab, SFmode, HFmode)))
 	pcum->pcs_variant = ARM_PCS_AAPCS;
  
+      /* We must pass arguments to double-precision helper functions in core
+         registers if we only have hardware support for single-precision
+	 arithmetic, even if we are using the hard-float ABI.  */
+      if (TARGET_VFP
+          && (rtx_equal_p (libname, optab_libfunc (add_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (sdiv_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (smul_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (neg_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (sub_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (eq_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (lt_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (le_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (ge_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (gt_optab, DFmode))
+	      || rtx_equal_p (libname, optab_libfunc (unord_optab, DFmode))
+	      || rtx_equal_p (libname, convert_optab_libfunc (sext_optab,
+							      DFmode, SFmode))
+	      || rtx_equal_p (libname, convert_optab_libfunc (trunc_optab,
+							      SFmode, DFmode))
+	      || rtx_equal_p (libname, convert_optab_libfunc (sfix_optab,
+							      SImode, DFmode))
+	      || rtx_equal_p (libname, convert_optab_libfunc (ufix_optab,
+							      SImode, DFmode))))
+        pcum->pcs_variant = ARM_PCS_AAPCS;
+ 
       pcum->aapcs_ncrn = pcum->aapcs_next_ncrn = 0;
       pcum->aapcs_reg = NULL_RTX;
       pcum->aapcs_partial = 0;
@@ -4633,8 +4760,8 @@
     return false;
 
   /* Never tailcall something for which we have no decl, or if we
-     are in Thumb mode.  */
-  if (decl == NULL || TARGET_THUMB)
+     are generating code for Thumb-1.  */
+  if (decl == NULL || !TARGET_32BIT)
     return false;
 
   /* The PIC register is live on entry to VxWorks PLT entries, so we
@@ -6740,6 +6867,17 @@
 	*total = COSTS_N_INSNS (4);
       return true;
 
+    case CONST_VECTOR:
+      if (TARGET_NEON
+	  && TARGET_HARD_FLOAT
+	  && outer == SET
+	  && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
+	  && neon_immediate_valid_for_move (x, mode, NULL, NULL))
+	*total = COSTS_N_INSNS (1);
+      else
+	*total = COSTS_N_INSNS (4);
+      return true;
+
     default:
       *total = COSTS_N_INSNS (4);
       return false;
@@ -6967,6 +7105,17 @@
       *total = COSTS_N_INSNS (4);
       return true;
 
+    case CONST_VECTOR:
+      if (TARGET_NEON
+	  && TARGET_HARD_FLOAT
+	  && outer_code == SET
+	  && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
+	  && neon_immediate_valid_for_move (x, mode, NULL, NULL))
+	*total = COSTS_N_INSNS (1);
+      else
+	*total = COSTS_N_INSNS (4);
+      return true;
+
     case HIGH:
     case LO_SUM:
       /* We prefer constant pool entries to MOVW/MOVT pairs, so bump the
@@ -6983,13 +7132,381 @@
     }
 }
 
+static bool
+thumb2_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
+		       int *total)
+{
+  /* Attempt to give a lower cost to RTXs which can optimistically be
+     represented as short insns, assuming that the right conditions will hold
+     later (e.g. low registers will be chosen if a short insn requires them). 
+     
+     Note that we don't make wide insns cost twice as much as narrow insns,
+     because we can't prove that a particular RTX will actually use a narrow
+     insn, because not enough information is available (e.g., we don't know
+     which hard registers pseudos will be assigned).  Consider these to be
+     "expected" sizes/weightings.
+     
+     (COSTS_NARROW_INSNS has the same weight as COSTS_N_INSNS.)  */
+
+#define COSTS_NARROW_INSNS(N) ((N) * 4)
+#define COSTS_WIDE_INSNS(N) ((N) * 6)
+#define THUMB2_LIBCALL_COST COSTS_WIDE_INSNS (2)
+  enum machine_mode mode = GET_MODE (x);
+  
+  switch (code)
+    {
+    case MEM:
+      if (REG_P (XEXP (x, 0)))
+        {
+          /* Hopefully this will use a narrow ldm/stm insn.  */
+	  *total = COSTS_NARROW_INSNS (1);
+	  return true;
+	}
+      else if ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+	        && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+	       || reg_mentioned_p (virtual_stack_vars_rtx, XEXP (x, 0))
+	       || reg_mentioned_p (stack_pointer_rtx, XEXP (x, 0)))
+	{
+          *total = COSTS_NARROW_INSNS (ARM_NUM_REGS (mode));
+	  return true;
+	}
+      else if (GET_CODE (XEXP (x, 0)) == PLUS)
+	{
+	  rtx plus = XEXP (x, 0);
+
+	  if (GET_CODE (XEXP (plus, 1)) == CONST_INT)
+            {
+	      HOST_WIDE_INT cst = INTVAL (XEXP (plus, 1));
+
+	      if (cst >= 0 && cst < 256)
+		*total = COSTS_NARROW_INSNS (ARM_NUM_REGS (mode));
+	      else
+		*total = COSTS_WIDE_INSNS (ARM_NUM_REGS (mode));
+	
+	      *total += rtx_cost (XEXP (plus, 0), code, false);
+	      
+	      return true;
+	    }
+	}
+
+      *total = COSTS_NARROW_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case DIV:
+    case MOD:
+    case UDIV:
+    case UMOD:
+      if (arm_arch_hwdiv)
+	*total = COSTS_WIDE_INSNS (1);
+      else
+	*total = THUMB2_LIBCALL_COST;
+      return false;
+    
+    case ROTATE:
+      if (mode == SImode && REG_P (XEXP (x, 1)))
+	{
+	  *total = COSTS_WIDE_INSNS (1) + COSTS_NARROW_INSNS (1)
+		   + rtx_cost (XEXP (x, 0), code, false);
+	  return true;
+	}
+      /* Fall through */
+
+    case ASHIFT:
+    case LSHIFTRT:
+    case ASHIFTRT:
+      if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT)
+	{
+	  *total = COSTS_WIDE_INSNS (3) + rtx_cost (XEXP (x, 0), code, false);
+	  return true;
+	}
+      else if (mode == SImode)
+        {
+	  *total = COSTS_NARROW_INSNS (1);
+	  return false;
+	}
+
+      /* Needs a libcall.  */
+      *total = THUMB2_LIBCALL_COST;
+      return false;
+
+    case ROTATERT:
+      if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT)
+	{
+	  *total = COSTS_WIDE_INSNS (3) + rtx_cost (XEXP (x, 0), code, false);
+	  return true;
+	}
+      else if (mode == SImode)
+        {
+	  if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	    *total = COSTS_WIDE_INSNS (1) + rtx_cost (XEXP (x, 0), code, false);
+	  else
+	    *total = COSTS_NARROW_INSNS (1)
+		     + rtx_cost (XEXP (x, 0), code, false);
+	  return true;
+	}
+
+      /* Needs a libcall.  */
+      *total = THUMB2_LIBCALL_COST;
+      return false;
+
+    case MINUS:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+	  && (mode == SFmode || !TARGET_VFP_SINGLE))
+	{
+	  *total = COSTS_WIDE_INSNS (1);
+	  return false;
+	}
+
+      if (mode == SImode)
+	{
+	  enum rtx_code subcode0 = GET_CODE (XEXP (x, 0));
+	  enum rtx_code subcode1 = GET_CODE (XEXP (x, 1));
+
+	  if (subcode0 == ROTATE || subcode0 == ROTATERT || subcode0 == ASHIFT
+	      || subcode0 == LSHIFTRT || subcode0 == ASHIFTRT
+	      || subcode1 == ROTATE || subcode1 == ROTATERT
+	      || subcode1 == ASHIFT || subcode1 == LSHIFTRT
+	      || subcode1 == ASHIFTRT)
+	    {
+	      /* It's just the cost of the two operands.  */
+	      *total = 0;
+	      return false;
+	    }
+
+	  if (subcode1 == CONST_INT)
+	    {
+	      HOST_WIDE_INT cst = INTVAL (XEXP (x, 1));
+
+	      if (cst >= 0 && cst < 256)
+		*total = COSTS_NARROW_INSNS (1);
+	      else
+		*total = COSTS_WIDE_INSNS (1);
+
+	      *total += rtx_cost (XEXP (x, 0), code, false);
+
+	      return true;
+	    }
+
+	  *total = COSTS_NARROW_INSNS (1);
+	  return false;
+	}
+
+      *total = COSTS_WIDE_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case PLUS:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+	  && (mode == SFmode || !TARGET_VFP_SINGLE))
+	{
+	  *total = COSTS_WIDE_INSNS (1);
+	  return false;
+	}
+
+      /* Fall through */
+    case AND: case XOR: case IOR:
+      if (mode == SImode)
+	{
+	  enum rtx_code subcode = GET_CODE (XEXP (x, 0));
+
+	  if (subcode == ROTATE || subcode == ROTATERT || subcode == ASHIFT
+	      || subcode == LSHIFTRT || subcode == ASHIFTRT
+	      || (code == AND && subcode == NOT))
+	    {
+	      /* It's just the cost of the two operands.  */
+	      *total = 0;
+	      return false;
+	    }
+
+	  if (code == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
+	    {
+	      HOST_WIDE_INT cst = INTVAL (XEXP (x, 1));
+
+	      if ((reg_mentioned_p (virtual_stack_vars_rtx, XEXP (x, 0))
+		   || reg_mentioned_p (stack_pointer_rtx, XEXP (x, 0)))
+		  && cst > -512 && cst < 1024)
+		/* Only approximately correct, depending on destination
+		   register.  */
+		*total = COSTS_NARROW_INSNS (1);
+	      else if (cst > -256 && cst < 256)
+	        *total = COSTS_NARROW_INSNS (1);
+	      else
+		*total = COSTS_WIDE_INSNS (1);
+
+	      *total += rtx_cost (XEXP (x, 0), code, false);
+
+	      return true;
+	    }
+	  
+	  if (subcode == MULT
+	      && power_of_two_operand (XEXP (XEXP (x, 0), 1), mode))
+	    {
+	      *total = COSTS_WIDE_INSNS (1)
+		       + rtx_cost (XEXP (x, 1), code, false);
+	      return true;
+	    }
+	}
+
+      *total = COSTS_NARROW_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case MULT:
+      if (mode == SImode && GET_CODE (XEXP (x, 1)) != CONST_INT)
+	{
+	  /* Might be using muls.  */
+	  *total = COSTS_NARROW_INSNS (1);
+	  return false;
+	}
+      *total = COSTS_WIDE_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case NEG:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+	  && (mode == SFmode || !TARGET_VFP_SINGLE))
+	{
+	  *total = COSTS_WIDE_INSNS (1);
+	  return false;
+	}
+
+      /* Fall through */
+    case NOT:
+      if (mode == SImode)
+        {
+	  *total = COSTS_NARROW_INSNS (1);
+	  return false;
+	}
+      *total = COSTS_WIDE_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case IF_THEN_ELSE:
+      *total = COSTS_NARROW_INSNS (1);
+      return false;
+
+    case COMPARE:
+      if (cc_register (XEXP (x, 0), VOIDmode))
+	*total = 0;
+      else
+	*total = COSTS_NARROW_INSNS (1);
+      return false;
+
+    case ABS:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+	  && (mode == SFmode || !TARGET_VFP_SINGLE))
+	*total = COSTS_WIDE_INSNS (1);
+      else
+	*total = COSTS_NARROW_INSNS (ARM_NUM_REGS (mode)) * 2;
+      return false;
+
+    case SIGN_EXTEND:
+      if (GET_MODE_SIZE (mode) <= 4)
+        *total = GET_CODE (XEXP (x, 0)) == MEM ? 0 : COSTS_NARROW_INSNS (1);
+      else
+        *total = COSTS_NARROW_INSNS (1)
+		 + COSTS_WIDE_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case ZERO_EXTEND:
+      if (GET_MODE_SIZE (mode) > 4)
+        *total = COSTS_WIDE_INSNS (ARM_NUM_REGS (mode) - 1);
+      else if (GET_CODE (XEXP (x, 0)) == MEM)
+        *total = 0;
+      else
+        *total = COSTS_NARROW_INSNS (1);
+      return false;
+
+    case CONST_INT:
+      {
+	HOST_WIDE_INT cst = INTVAL (x);
+
+	switch (outer_code)
+          {
+	  case PLUS:
+	    if (cst > -256 && cst < 256)
+	      *total = 0;
+	    else
+	      /* See note about optabs below.  */
+	      *total = COSTS_N_INSNS (1);
+	    return true;
+
+	  case MINUS:
+	  case COMPARE:
+	    if (cst >= 0 && cst < 256)
+	      *total = 0;
+	    else
+	      /* See note about optabs below.  */
+	      *total = COSTS_N_INSNS (1);
+	    return true;
+	  
+	  case ASHIFT:
+	  case ASHIFTRT:
+	  case LSHIFTRT:
+	    *total = 0;
+	    return true;
+	  
+	  default:
+	    /* Constants are compared explicitly against COSTS_N_INSNS (1) in
+	       optabs.c, creating an alternative, larger code sequence for more
+	       expensive constants).  So, it doesn't pay to make some constants
+	       cost more than this.  */
+	    *total = COSTS_N_INSNS (1);
+	  }
+	return true;
+      }
+
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      *total = COSTS_WIDE_INSNS (2);
+      return true;
+
+    case CONST_DOUBLE:
+      *total = COSTS_WIDE_INSNS (4);
+      return true;
+
+    case CONST_VECTOR:
+      if (TARGET_NEON
+	  && TARGET_HARD_FLOAT
+	  && outer_code == SET
+	  && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
+	  && neon_immediate_valid_for_move (x, mode, NULL, NULL))
+	*total = COSTS_WIDE_INSNS (1);
+      else
+	*total = COSTS_WIDE_INSNS (4);
+      return true;
+
+    case HIGH:
+    case LO_SUM:
+      /* We prefer constant pool entries to MOVW/MOVT pairs, so bump the
+	 cost of these slightly.  */
+      *total = COSTS_WIDE_INSNS (1) + 1;
+      return true;
+
+    default:
+      if (mode != VOIDmode)
+	*total = COSTS_WIDE_INSNS (ARM_NUM_REGS (mode));
+      else
+	/* A guess (inherited from arm_size_rtx_costs).  */
+	*total = COSTS_WIDE_INSNS (4);
+      return false;
+    }
+  
+  return true;
+#undef THUMB2_LIBCALL_COST
+#undef COSTS_WIDE_INSNS
+#undef COSTS_NARROW_INSNS
+}
+
 /* RTX costs when optimizing for size.  */
 static bool
 arm_rtx_costs (rtx x, int code, int outer_code, int *total,
 	       bool speed)
 {
   if (!speed)
-    return arm_size_rtx_costs (x, code, outer_code, total);
+    {
+      if (TARGET_THUMB2)
+	return thumb2_size_rtx_costs (x, code, outer_code, total);
+      else
+	return arm_size_rtx_costs (x, code, outer_code, total);
+    }
   else
     return all_cores[(int)arm_tune].rtx_costs (x, code, outer_code, total,
 					       speed);
@@ -7621,11 +8138,14 @@
    vmov  i64    17    aaaaaaaa bbbbbbbb cccccccc dddddddd
                       eeeeeeee ffffffff gggggggg hhhhhhhh
    vmov  f32    18    aBbbbbbc defgh000 00000000 00000000
+   vmov  f32    19    00000000 00000000 00000000 00000000
 
    For case 18, B = !b. Representable values are exactly those accepted by
    vfp3_const_double_index, but are output as floating-point numbers rather
    than indices.
 
+   For case 19, we will change it to vmov.i32 when assembling.
+
    Variants 0-5 (inclusive) may also be used as immediates for the second
    operand of VORR/VBIC instructions.
 
@@ -7668,7 +8188,7 @@
       rtx el0 = CONST_VECTOR_ELT (op, 0);
       REAL_VALUE_TYPE r0;
 
-      if (!vfp3_const_double_rtx (el0))
+      if (!vfp3_const_double_rtx (el0) && el0 != CONST0_RTX (GET_MODE (el0)))
         return -1;
 
       REAL_VALUE_FROM_CONST_DOUBLE (r0, el0);
@@ -7690,7 +8210,10 @@
       if (elementwidth)
         *elementwidth = 0;
 
-      return 18;
+      if (el0 == CONST0_RTX (GET_MODE (el0)))
+	return 19;
+      else
+	return 18;
     }
 
   /* Splat vector constant out into a byte vector.  */
@@ -7921,25 +8444,198 @@
     }
 }
 
-/* Initialize a vector with non-constant elements.  FIXME: We can do better
-   than the current implementation (building a vector on the stack and then
-   loading it) in many cases.  See rs6000.c.  */
+/* If VALS is a vector constant that can be loaded into a register
+   using VDUP, generate instructions to do so and return an RTX to
+   assign to the register.  Otherwise return NULL_RTX.  */
+
+static rtx
+neon_vdup_constant (rtx vals)
+{
+  enum machine_mode mode = GET_MODE (vals);
+  enum machine_mode inner_mode = GET_MODE_INNER (mode);
+  int n_elts = GET_MODE_NUNITS (mode);
+  bool all_same = true;
+  rtx x;
+  int i;
+
+  if (GET_CODE (vals) != CONST_VECTOR || GET_MODE_SIZE (inner_mode) > 4)
+    return NULL_RTX;
+
+  for (i = 0; i < n_elts; ++i)
+    {
+      x = XVECEXP (vals, 0, i);
+      if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
+	all_same = false;
+    }
+
+  if (!all_same)
+    /* The elements are not all the same.  We could handle repeating
+       patterns of a mode larger than INNER_MODE here (e.g. int8x8_t
+       {0, C, 0, C, 0, C, 0, C} which can be loaded using
+       vdup.i16).  */
+    return NULL_RTX;
+
+  /* We can load this constant by using VDUP and a constant in a
+     single ARM register.  This will be cheaper than a vector
+     load.  */
+
+  x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, 0));
+  return gen_rtx_VEC_DUPLICATE (mode, x);
+}
+
+/* Generate code to load VALS, which is a PARALLEL containing only
+   constants (for vec_init) or CONST_VECTOR, efficiently into a
+   register.  Returns an RTX to copy into the register, or NULL_RTX
+   for a PARALLEL that can not be converted into a CONST_VECTOR.  */
+
+rtx
+neon_make_constant (rtx vals)
+{
+  enum machine_mode mode = GET_MODE (vals);
+  rtx target;
+  rtx const_vec = NULL_RTX;
+  int n_elts = GET_MODE_NUNITS (mode);
+  int n_const = 0;
+  int i;
+
+  if (GET_CODE (vals) == CONST_VECTOR)
+    const_vec = vals;
+  else if (GET_CODE (vals) == PARALLEL)
+    {
+      /* A CONST_VECTOR must contain only CONST_INTs and
+	 CONST_DOUBLEs, but CONSTANT_P allows more (e.g. SYMBOL_REF).
+	 Only store valid constants in a CONST_VECTOR.  */
+      for (i = 0; i < n_elts; ++i)
+	{
+	  rtx x = XVECEXP (vals, 0, i);
+	  if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
+	    n_const++;
+	}
+      if (n_const == n_elts)
+	const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+    }
+  else
+    gcc_unreachable ();
+
+  if (const_vec != NULL
+      && neon_immediate_valid_for_move (const_vec, mode, NULL, NULL))
+    /* Load using VMOV.  On Cortex-A8 this takes one cycle.  */
+    return const_vec;
+  else if ((target = neon_vdup_constant (vals)) != NULL_RTX)
+    /* Loaded using VDUP.  On Cortex-A8 the VDUP takes one NEON
+       pipeline cycle; creating the constant takes one or two ARM
+       pipeline cycles.  */
+    return target;
+  else if (const_vec != NULL_RTX)
+    /* Load from constant pool.  On Cortex-A8 this takes two cycles
+       (for either double or quad vectors).  We can not take advantage
+       of single-cycle VLD1 because we need a PC-relative addressing
+       mode.  */
+    return const_vec;
+  else
+    /* A PARALLEL containing something not valid inside CONST_VECTOR.
+       We can not construct an initializer.  */
+    return NULL_RTX;
+}
+
+/* Initialize vector TARGET to VALS.  */
 
 void
 neon_expand_vector_init (rtx target, rtx vals)
 {
   enum machine_mode mode = GET_MODE (target);
-  enum machine_mode inner = GET_MODE_INNER (mode);
-  unsigned int i, n_elts = GET_MODE_NUNITS (mode);
-  rtx mem;
+  enum machine_mode inner_mode = GET_MODE_INNER (mode);
+  int n_elts = GET_MODE_NUNITS (mode);
+  int n_var = 0, one_var = -1;
+  bool all_same = true;
+  rtx x, mem;
+  int i;
 
-  gcc_assert (VECTOR_MODE_P (mode));
+  for (i = 0; i < n_elts; ++i)
+    {
+      x = XVECEXP (vals, 0, i);
+      if (!CONSTANT_P (x))
+	++n_var, one_var = i;
+
+      if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
+	all_same = false;
+    }
 
+  if (n_var == 0)
+    {
+      rtx constant = neon_make_constant (vals);
+      if (constant != NULL_RTX)
+	{
+	  emit_move_insn (target, constant);
+	  return;
+	}
+    }
+
+  /* Splat a single non-constant element if we can.  */
+  if (all_same && GET_MODE_SIZE (inner_mode) <= 4)
+    {
+      x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, 0));
+      emit_insn (gen_rtx_SET (VOIDmode, target,
+			      gen_rtx_VEC_DUPLICATE (mode, x)));
+      return;
+    }
+
+  /* One field is non-constant.  Load constant then overwrite varying
+     field.  This is more efficient than using the stack.  */
+  if (n_var == 1)
+    {
+      rtx copy = copy_rtx (vals);
+      rtx index = GEN_INT (one_var);
+
+      /* Load constant part of vector, substitute neighboring value for
+	 varying element.  */
+      XVECEXP (copy, 0, one_var) = XVECEXP (vals, 0, (one_var + 1) % n_elts);
+      neon_expand_vector_init (target, copy);
+
+      /* Insert variable.  */
+      x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, one_var));
+      switch (mode)
+	{
+	case V8QImode:
+	  emit_insn (gen_neon_vset_lanev8qi (target, x, target, index));
+	  break;
+	case V16QImode:
+	  emit_insn (gen_neon_vset_lanev16qi (target, x, target, index));
+	  break;
+	case V4HImode:
+	  emit_insn (gen_neon_vset_lanev4hi (target, x, target, index));
+	  break;
+	case V8HImode:
+	  emit_insn (gen_neon_vset_lanev8hi (target, x, target, index));
+	  break;
+	case V2SImode:
+	  emit_insn (gen_neon_vset_lanev2si (target, x, target, index));
+	  break;
+	case V4SImode:
+	  emit_insn (gen_neon_vset_lanev4si (target, x, target, index));
+	  break;
+	case V2SFmode:
+	  emit_insn (gen_neon_vset_lanev2sf (target, x, target, index));
+	  break;
+	case V4SFmode:
+	  emit_insn (gen_neon_vset_lanev4sf (target, x, target, index));
+	  break;
+	case V2DImode:
+	  emit_insn (gen_neon_vset_lanev2di (target, x, target, index));
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      return;
+    }
+
+  /* Construct the vector in memory one field at a time
+     and load the whole vector.  */
   mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
   for (i = 0; i < n_elts; i++)
-    emit_move_insn (adjust_address_nv (mem, inner, i * GET_MODE_SIZE (inner)),
-                   XVECEXP (vals, 0, i));
-
+    emit_move_insn (adjust_address_nv (mem, inner_mode,
+				    i * GET_MODE_SIZE (inner_mode)),
+		    XVECEXP (vals, 0, i));
   emit_move_insn (target, mem);
 }
 
@@ -9598,6 +10294,55 @@
       && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
     return CC_Cmode;
 
+  if (GET_MODE (x) == DImode || GET_MODE (y) == DImode)
+    {
+      /* To keep things simple, always use the Cirrus cfcmp64 if it is
+	 available.  */
+      if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK)
+	return CCmode;
+
+      switch (op)
+	{
+	case EQ:
+	case NE:
+	  /* A DImode comparison against zero can be implemented by
+	     or'ing the two halves together.  */
+	  if (y == const0_rtx)
+	    return CC_Zmode;
+
+	  /* We can do an equality test in three Thumb instructions.  */
+	  if (!TARGET_ARM)
+	    return CC_Zmode;
+
+	  /* FALLTHROUGH */
+
+	case LTU:
+	case LEU:
+	case GTU:
+	case GEU:
+	  /* DImode unsigned comparisons can be implemented by cmp +
+	     cmpeq without a scratch register.  Not worth doing in
+	     Thumb-2.  */
+	  if (TARGET_ARM)
+	    return CC_CZmode;
+
+	  /* FALLTHROUGH */
+
+	case LT:
+	case LE:
+	case GT:
+	case GE:
+	  /* DImode signed and unsigned comparisons can be implemented
+	     by cmp + sbcs with a scratch register, but that does not
+	     set the Z flag - we must reverse GT/LE/GTU/LEU.  */
+	  gcc_assert (op != EQ && op != NE);
+	  return CC_NCVmode;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+
   return CCmode;
 }
 
@@ -9607,10 +10352,39 @@
 rtx
 arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
 {
-  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
-  rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+  enum machine_mode mode;
+  rtx cc_reg;
+  int dimode_comparison = GET_MODE (x) == DImode || GET_MODE (y) == DImode;
 
-  emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
+  /* We might have X as a constant, Y as a register because of the predicates
+     used for cmpdi.  If so, force X to a register here.  */
+  if (dimode_comparison && !REG_P (x))
+    x = force_reg (DImode, x);
+
+  mode = SELECT_CC_MODE (code, x, y);
+  cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+
+  if (dimode_comparison
+      && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
+      && mode != CC_CZmode)
+    {
+      rtx clobber, set;
+
+      /* To compare two non-zero values for equality, XOR them and
+	 then compare against zero.  Not used for ARM mode; there
+	 CC_CZmode is cheaper.  */
+      if (mode == CC_Zmode && y != const0_rtx)
+	{
+	  x = expand_binop (DImode, xor_optab, x, y, NULL_RTX, 0, OPTAB_WIDEN);
+	  y = const0_rtx;
+	}
+      /* A scratch register is required.  */
+      clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode));
+      set = gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y));
+      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));
+    }
+  else
+    emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
 
   return cc_reg;
 }
@@ -10942,6 +11716,34 @@
   return false;
 }
 
+/* Return true if it is possible to inline both the high and low parts
+   of a 64-bit constant into 32-bit data processing instructions.  */
+bool
+arm_const_double_by_immediates (rtx val)
+{
+  enum machine_mode mode = GET_MODE (val);
+  rtx part;
+
+  if (mode == VOIDmode)
+    mode = DImode;
+
+  part = gen_highpart_mode (SImode, mode, val);
+
+  gcc_assert (GET_CODE (part) == CONST_INT);
+
+  if (!const_ok_for_arm (INTVAL (part)))
+    return false;
+
+  part = gen_lowpart (SImode, val);
+
+  gcc_assert (GET_CODE (part) == CONST_INT);
+
+  if (!const_ok_for_arm (INTVAL (part)))
+    return false;
+
+  return true;
+}
+
 /* Scan INSN and note any of its operands that need fixing.
    If DO_PUSHES is false we do not actually push any of the fixups
    needed.  The function returns TRUE if any fixups were needed/pushed.
@@ -11526,7 +12328,9 @@
 const char *
 output_call_mem (rtx *operands)
 {
-  if (TARGET_INTERWORK && !arm_arch5)
+  gcc_assert (!arm_arch5);
+
+  if (TARGET_INTERWORK)
     {
       output_asm_insn ("ldr%?\t%|ip, %0", operands);
       output_asm_insn ("mov%?\t%|lr, %|pc", operands);
@@ -11538,16 +12342,11 @@
 	 first instruction.  It's safe to use IP as the target of the
 	 load since the call will kill it anyway.  */
       output_asm_insn ("ldr%?\t%|ip, %0", operands);
-      if (arm_arch5)
-	output_asm_insn ("blx%?\t%|ip", operands);
+      output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+      if (arm_arch4t)
+	output_asm_insn ("bx%?\t%|ip", operands);
       else
-	{
-	  output_asm_insn ("mov%?\t%|lr, %|pc", operands);
-	  if (arm_arch4t)
-	    output_asm_insn ("bx%?\t%|ip", operands);
-	  else
-	    output_asm_insn ("mov%?\t%|pc, %|ip", operands);
-	}
+	output_asm_insn ("mov%?\t%|pc, %|ip", operands);
     }
   else
     {
@@ -12575,6 +13374,20 @@
 	  && crtl->uses_pic_offset_table)
 	save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
     }
+  else if (IS_VOLATILE(func_type))
+    {
+      /* For noreturn functions we historically omitted register saves
+	 altogether.  However this really messes up debugging.  As a
+	 compromise save just the fame pointers.  Combined with the link
+	 register saved elsewhere this should be sufficient to get
+	 a backtrace.  */
+      if (frame_pointer_needed)
+	save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
+      if (df_regs_ever_live_p (ARM_HARD_FRAME_POINTER_REGNUM))
+	save_reg_mask |= 1 << ARM_HARD_FRAME_POINTER_REGNUM;
+      if (df_regs_ever_live_p (THUMB_HARD_FRAME_POINTER_REGNUM))
+	save_reg_mask |= 1 << THUMB_HARD_FRAME_POINTER_REGNUM;
+    }
   else
     {
       /* In the normal case we only need to save those registers
@@ -12661,11 +13474,6 @@
       | (1 << LR_REGNUM)
       | (1 << PC_REGNUM);
 
-  /* Volatile functions do not return, so there
-     is no need to save any other registers.  */
-  if (IS_VOLATILE (func_type))
-    return save_reg_mask;
-
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
   /* Decide if we need to save the link register.
@@ -12963,8 +13771,10 @@
 		  sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
 		}
 	    }
-	  else
+	  else if (TARGET_ARM)
 	    sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
+	  else
+	    sprintf (instr, "pop\t{");
 
 	  p = instr + strlen (instr);
 
@@ -13511,24 +14321,29 @@
 
       if (TARGET_HARD_FLOAT && TARGET_VFP)
 	{
-	  start_reg = FIRST_VFP_REGNUM;
-	  for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
+	  int end_reg = LAST_VFP_REGNUM + 1;
+
+	  /* Scan the registers in reverse order.  We need to match
+	     any groupings made in the prologue and generate matching
+	     pop operations.  */
+	  for (reg = LAST_VFP_REGNUM - 1; reg >= FIRST_VFP_REGNUM; reg -= 2)
 	    {
 	      if ((!df_regs_ever_live_p (reg) || call_used_regs[reg])
-		  && (!df_regs_ever_live_p (reg + 1) || call_used_regs[reg + 1]))
+		  && (!df_regs_ever_live_p (reg + 1)
+		      || call_used_regs[reg + 1]))
 		{
-		  if (start_reg != reg)
+		  if (end_reg > reg + 2)
 		    vfp_output_fldmd (f, SP_REGNUM,
-				      (start_reg - FIRST_VFP_REGNUM) / 2,
-				      (reg - start_reg) / 2);
-		  start_reg = reg + 2;
+				      (reg + 2 - FIRST_VFP_REGNUM) / 2,
+				      (end_reg - (reg + 2)) / 2);
+		  end_reg = reg;
 		}
 	    }
-	  if (start_reg != reg)
-	    vfp_output_fldmd (f, SP_REGNUM,
-			      (start_reg - FIRST_VFP_REGNUM) / 2,
-			      (reg - start_reg) / 2);
+	  if (end_reg > reg + 2)
+	    vfp_output_fldmd (f, SP_REGNUM, 0,
+			      (end_reg - (reg + 2)) / 2);
 	}
+
       if (TARGET_IWMMXT)
 	for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
 	  if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
@@ -14845,8 +15660,18 @@
 	 the value being loaded is big-wordian or little-wordian.  The
 	 order of the two register loads can matter however, if the address
 	 of the memory location is actually held in one of the registers
-	 being overwritten by the load.  */
+	 being overwritten by the load.
+
+	 The 'Q' and 'R' constraints are also available for 64-bit
+	 constants.  */
     case 'Q':
+      if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
+	{
+	  rtx part = gen_lowpart (SImode, x);
+	  fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part));
+	  return;
+	}
+
       if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
 	{
 	  output_operand_lossage ("invalid operand for code '%c'", code);
@@ -14857,6 +15682,18 @@
       return;
 
     case 'R':
+      if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
+	{
+	  enum machine_mode mode = GET_MODE (x);
+	  rtx part;
+
+	  if (mode == VOIDmode)
+	    mode = DImode;
+	  part = gen_highpart_mode (SImode, mode, x);
+	  fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part));
+	  return;
+	}
+
       if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
 	{
 	  output_operand_lossage ("invalid operand for code '%c'", code);
@@ -15200,6 +16037,30 @@
       }
       return;
 
+    /* Translate an S register number into a D register number and element index.  */
+    case 'y':
+      {
+        int mode = GET_MODE (x);
+        int regno;
+
+        if (GET_MODE_SIZE (mode) != 4 || GET_CODE (x) != REG)
+          {
+	    output_operand_lossage ("invalid operand for code '%c'", code);
+	    return;
+          }
+
+        regno = REGNO (x);
+        if (!VFP_REGNO_OK_FOR_SINGLE (regno))
+          {
+	    output_operand_lossage ("invalid operand for code '%c'", code);
+	    return;
+          }
+
+	regno = regno - FIRST_VFP_REGNUM;
+	fprintf (stream, "d%d[%d]", regno / 2, regno % 2);
+      }
+      return;
+
     /* Register specifier for vld1.16/vst1.16.  Translate the S register
        number into a D register number and element index.  */
     case 'z':
@@ -15533,6 +16394,28 @@
       default: gcc_unreachable ();
       }
 
+    case CC_CZmode:
+      switch (comp_code)
+	{
+	case NE: return ARM_NE;
+	case EQ: return ARM_EQ;
+	case GEU: return ARM_CS;
+	case GTU: return ARM_HI;
+	case LEU: return ARM_LS;
+	case LTU: return ARM_CC;
+	default: gcc_unreachable ();
+	}
+
+    case CC_NCVmode:
+      switch (comp_code)
+	{
+	case GE: return ARM_GE;
+	case LT: return ARM_LT;
+	case GEU: return ARM_CS;
+	case LTU: return ARM_CC;
+	default: gcc_unreachable ();
+	}
+
     case CCmode:
       switch (comp_code)
 	{
@@ -19772,7 +20655,6 @@
 	}
       else
 	{
-	  int set_float_abi_attributes = 0;
 	  fpu_name = arm_fpu_desc->name;
 	  if (arm_fp_model == ARM_FP_MODEL_VFP)
 	    {
@@ -21082,6 +21964,7 @@
     {
     case cortexr4:
     case cortexr4f:
+    case cortexa5:
     case cortexa8:
     case cortexa9:
     case marvell_f:
@@ -21140,7 +22023,7 @@
       && lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type))
     {
       static bool warned;
-      if (!warned && warn_psabi)
+      if (!warned && warn_psabi && !in_system_header)
 	{
 	  warned = true;
 	  inform (input_location,
@@ -21291,5 +22174,28 @@
   return TARGET_NEON && !BYTES_BIG_ENDIAN;
 }
 
-#include "gt-arm.h"
+int
+arm_major_arch (void)
+{
+  if ((insn_flags & FL_FOR_ARCH6) == FL_FOR_ARCH6)
+    return 6;
+  else if ((insn_flags & FL_FOR_ARCH5) == FL_FOR_ARCH5)
+    return 5;
+  else if ((insn_flags & FL_FOR_ARCH4) == FL_FOR_ARCH4)
+    return 4;
+  else if ((insn_flags & FL_FOR_ARCH3) == FL_FOR_ARCH3)
+    return 3;
+  else if ((insn_flags & FL_FOR_ARCH2) == FL_FOR_ARCH2)
+    return 2;
+  
+  /* This should gives us a nice ICE somewhere.  */
+  return -1;
+}
 
+bool
+arm_thumb_arch_p (void)
+{
+  return (insn_flags & FL_THUMB) == FL_THUMB;
+}
+
+#include "gt-arm.h"
diff -Naur a/src/gcc/config/arm/arm-cores.def b/src/gcc/config/arm/arm-cores.def
--- a/src/gcc/config/arm/arm-cores.def	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/arm-cores.def	2010-03-30 10:39:38.000000000 +0300
@@ -125,6 +125,7 @@
 ARM_CORE("cortex-a9",	  cortexa9,	7A,				 FL_LDSCHED, 9e)
 ARM_CORE("cortex-r4",	  cortexr4,	7R,				 FL_LDSCHED, 9e)
 ARM_CORE("cortex-r4f",	  cortexr4f,	7R,				 FL_LDSCHED, 9e)
+ARM_CORE("cortex-m4",	  cortexm4,	7EM,				 FL_LDSCHED, 9e)
 ARM_CORE("cortex-m3",	  cortexm3,	7M,				 FL_LDSCHED, 9e)
 ARM_CORE("cortex-m1",	  cortexm1,	6M,				 FL_LDSCHED, 9e)
 ARM_CORE("cortex-m0",	  cortexm0,	6M,				 FL_LDSCHED, 9e)
diff -Naur a/src/gcc/config/arm/arm.h b/src/gcc/config/arm/arm.h
--- a/src/gcc/config/arm/arm.h	2009-10-14 21:55:23.000000000 +0300
+++ b/src/gcc/config/arm/arm.h	2010-04-08 10:44:38.000000000 +0300
@@ -574,7 +574,14 @@
 #define PREFERRED_STACK_BOUNDARY \
     (arm_abi == ARM_ABI_ATPCS ? 64 : STACK_BOUNDARY)
 
-#define FUNCTION_BOUNDARY  32
+/* There are two values that tweak function alignment: FUNCTION_BOUNDARY and
+   align_functions.  The former is used by default and the latter can override
+   the default, but only when optimizing for speed.  So FUNCTION_BOUNDARY is
+   the right place to tweak when optimizing for size.
+   In ARM mode, minimal allowed alignment is 32 bits.
+   In THUMB mode it is 16 bits; to avoid possible performance regressions
+   we use 16-bit alignment only when optimizing for size.  */
+#define FUNCTION_BOUNDARY  ((TARGET_THUMB && optimize_size) ? 16 : 32)
 
 /* The lowest bit is used to indicate Thumb-mode functions, so the
    vbit must go into the delta field of pointers to member
@@ -940,9 +947,6 @@
 #define MUST_USE_SJLJ_EXCEPTIONS 1
 #endif
 
-/* We can generate DWARF2 Unwind info, even though we don't use it.  */
-#define DWARF2_UNWIND_INFO 1
-
 /* Use r0 and r1 to pass exception handling information.  */
 #define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? N : INVALID_REGNUM)
 
@@ -1305,7 +1309,7 @@
    In general this is just CLASS, but for the Thumb core registers and
    immediate constants we prefer a LO_REGS class or a subset.  */
 #define PREFERRED_RELOAD_CLASS(X, CLASS)		\
-  (TARGET_ARM ? (CLASS) :				\
+  (TARGET_32BIT ? (CLASS) :				\
    ((CLASS) == GENERAL_REGS || (CLASS) == HI_REGS	\
     || (CLASS) == NO_REGS || (CLASS) == STACK_REG	\
    ? LO_REGS : (CLASS)))
@@ -1845,10 +1849,8 @@
 
 /* Determine if the epilogue should be output as RTL.
    You should override this if you define FUNCTION_EXTRA_EPILOGUE.  */
-/* This is disabled for Thumb-2 because it will confuse the
-   conditional insn counter.  */
 #define USE_RETURN_INSN(ISCOND)				\
-  (TARGET_ARM ? use_return_insn (ISCOND, NULL) : 0)
+  (TARGET_32BIT ? use_return_insn (ISCOND, NULL) : 0)
 
 /* Definitions for register eliminations.
 
@@ -2459,19 +2461,7 @@
    : reverse_condition (code))
 
 #define CANONICALIZE_COMPARISON(CODE, OP0, OP1)				\
-  do									\
-    {									\
-      if (GET_CODE (OP1) == CONST_INT					\
-          && ! (const_ok_for_arm (INTVAL (OP1))				\
-	        || (const_ok_for_arm (- INTVAL (OP1)))))		\
-        {								\
-          rtx const_op = OP1;						\
-          CODE = arm_canonicalize_comparison ((CODE), GET_MODE (OP0),	\
-					      &const_op);		\
-          OP1 = const_op;						\
-        }								\
-    }									\
-  while (0)
+  (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
 
 /* The arm5 clz instruction returns 32.  */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 32, 1)
diff -Naur a/src/gcc/config/arm/arm.md b/src/gcc/config/arm/arm.md
--- a/src/gcc/config/arm/arm.md	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/arm.md	2010-04-17 19:19:15.000000000 +0300
@@ -420,7 +420,7 @@
 
 (define_attr "generic_sched" "yes,no"
   (const (if_then_else 
-          (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9,marvell_f")
+          (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,marvell_f")
 	      (eq_attr "tune_cortexr4" "yes"))
           (const_string "no")
           (const_string "yes"))))
@@ -428,16 +428,31 @@
 (define_attr "generic_vfp" "yes,no"
   (const (if_then_else
 	  (and (eq_attr "fpu" "vfp")
-	       (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9,marvell_f")
+	       (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,marvell_f")
 	       (eq_attr "tune_cortexr4" "no"))
 	  (const_string "yes")
 	  (const_string "no"))))
 
+; Specifies which machine an alternative is tuned for.  Used to compute
+; attribute ENABLED.
+(define_attr "alt_tune" "all,onlya8,nota8" (const_string "all"))
+
+(define_attr "enabled" ""
+  (cond [(and (eq_attr "alt_tune" "onlya8")
+	      (not (eq_attr "tune" "cortexa8")))
+	 (const_int 0)
+
+	 (and (eq_attr "alt_tune" "nota8")
+	      (eq_attr "tune" "cortexa8"))
+	 (const_int 0)]
+	(const_int 1)))
+
 (include "arm-generic.md")
 (include "arm926ejs.md")
 (include "arm1020e.md")
 (include "arm1026ejs.md")
 (include "arm1136jfs.md")
+(include "cortex-a5.md")
 (include "cortex-a8.md")
 (include "cortex-a9.md")
 (include "cortex-r4.md")
@@ -502,9 +517,10 @@
 	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
 		 (match_operand:DI 2 "s_register_operand" "r,  0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
   "#"
-  "TARGET_32BIT && reload_completed"
+  "TARGET_32BIT && reload_completed
+   && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
   [(parallel [(set (reg:CC_C CC_REGNUM)
 		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
 				 (match_dup 1)))
@@ -703,7 +719,6 @@
   ""
 )
 
-;; ??? Make Thumb-2 variants which prefer low regs
 (define_insn "*addsi3_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
 	(compare:CC_NOOV
@@ -712,7 +727,7 @@
 	 (const_int 0)))
    (set (match_operand:SI 0 "s_register_operand" "=r,r")
 	(plus:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_32BIT"
+  "TARGET_ARM"
   "@
    add%.\\t%0, %1, %2
    sub%.\\t%0, %1, #%n2"
@@ -725,7 +740,7 @@
 	 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
 		  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
 	 (const_int 0)))]
-  "TARGET_32BIT"
+  "TARGET_ARM"
   "@
    cmn%?\\t%0, %1
    cmp%?\\t%0, #%n1"
@@ -1006,7 +1021,7 @@
 	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
 		  (match_operand:DI 2 "s_register_operand" "r,0,0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
+  "TARGET_32BIT && !TARGET_NEON"
   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")]
@@ -1274,8 +1289,8 @@
 		 (match_operand:SI 2 "register_operand" "l,0,0")))]
   "TARGET_THUMB1 && arm_arch6"
   "@
-   mul\\t%0, %2 
-   mul\\t%0, %1 
+   mul\\t%0, %2
+   mul\\t%0, %1
    mul\\t%0, %1"
   [(set_attr "length" "2")
    (set_attr "insn" "mul")]
@@ -1836,6 +1851,7 @@
 	  [(match_operand:DI 1 "s_register_operand" "")
 	   (match_operand:DI 2 "s_register_operand" "")]))]
   "TARGET_32BIT && reload_completed
+   && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
@@ -1909,11 +1925,19 @@
   }"
 )
 
-(define_insn "anddi3"
+(define_expand "anddi3"
+  [(set (match_operand:DI         0 "s_register_operand" "")
+	(and:DI (match_operand:DI 1 "s_register_operand" "")
+		(match_operand:DI 2 "neon_inv_logic_op2" "")))]
+  "TARGET_32BIT"
+  ""
+)
+
+(define_insn "*anddi3_insn"
   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
 	(and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
 		(match_operand:DI 2 "s_register_operand"   "r,r")))]
-  "TARGET_32BIT && ! TARGET_IWMMXT"
+  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
   "#"
   [(set_attr "length" "8")]
 )
@@ -2505,9 +2529,11 @@
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
 	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
 		(match_operand:DI 2 "s_register_operand" "0,r")))]
-  "TARGET_32BIT"
+  "TARGET_32BIT && !TARGET_NEON"
   "#"
-  "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
+  "TARGET_32BIT && reload_completed
+   && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
+   && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
   "
@@ -2635,11 +2661,19 @@
   [(set_attr "conds" "set")]
 )
 
-(define_insn "iordi3"
+(define_expand "iordi3"
+  [(set (match_operand:DI         0 "s_register_operand" "")
+	(ior:DI (match_operand:DI 1 "s_register_operand" "")
+		(match_operand:DI 2 "neon_logic_op2" "")))]
+  "TARGET_32BIT"
+  ""
+)
+
+(define_insn "*iordi3_insn"
   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
 	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
 		(match_operand:DI 2 "s_register_operand"   "r,r")))]
-  "TARGET_32BIT && ! TARGET_IWMMXT"
+  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
   "#"
   [(set_attr "length" "8")
    (set_attr "predicable" "yes")]
@@ -2760,11 +2794,19 @@
    (set_attr "insn" "orr")]
 )
 
-(define_insn "xordi3"
+(define_expand "xordi3"
+  [(set (match_operand:DI         0 "s_register_operand" "")
+	(xor:DI (match_operand:DI 1 "s_register_operand" "")
+		(match_operand:DI 2 "s_register_operand" "")))]
+  "TARGET_32BIT"
+  ""
+)
+
+(define_insn "*xordi3_insn"
   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
 	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
 		(match_operand:DI 2 "s_register_operand"   "r,r")))]
-  "TARGET_32BIT && !TARGET_IWMMXT"
+  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
   "#"
   [(set_attr "length" "8")
    (set_attr "predicable" "yes")]
@@ -8021,6 +8063,68 @@
                                         (const_int 4)))]
 )
 
+;; DImode comparisons.  The generic code generates branches that
+;; if-conversion can not reduce to a conditional compare, so we do
+;; that directly.
+
+(define_insn "*arm_cmpdi_insn"
+  [(set (reg:CC_NCV CC_REGNUM)
+	(compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
+			(match_operand:DI 1 "arm_di_operand"	   "rDi")))
+   (clobber (match_scratch:SI 2 "=r"))]
+  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+  "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
+  [(set_attr "conds" "set")
+   (set_attr "length" "8")]
+)
+
+(define_insn "*arm_cmpdi_unsigned"
+  [(set (reg:CC_CZ CC_REGNUM)
+	(compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
+		       (match_operand:DI 1 "arm_di_operand"	"rDi")))]
+  "TARGET_ARM"
+  "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
+  [(set_attr "conds" "set")
+   (set_attr "length" "8")]
+)
+
+(define_insn "*arm_cmpdi_zero"
+  [(set (reg:CC_Z CC_REGNUM)
+	(compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
+		      (const_int 0)))
+   (clobber (match_scratch:SI 1 "=r"))]
+  "TARGET_32BIT"
+  "orr%.\\t%1, %Q0, %R0"
+  [(set_attr "conds" "set")
+   (set_attr "insn" "orr")]
+)
+
+(define_insn "*thumb_cmpdi_zero"
+  [(set (reg:CC_Z CC_REGNUM)
+	(compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
+		      (const_int 0)))
+   (clobber (match_scratch:SI 1 "=l"))]
+  "TARGET_THUMB1"
+  "orr\\t%1, %Q0, %R0"
+  [(set_attr "conds" "set")
+   (set_attr "insn" "orr")
+   (set_attr "length" "2")]
+)
+
+(define_expand "cmpdi"
+  [(match_operand:DI 0 "cmpdi_operand" "")
+   (match_operand:DI 1 "cmpdi_operand" "")]
+  "TARGET_32BIT"
+  "{
+     /* We should not have two constants.  */
+     gcc_assert (GET_MODE (operands[0]) == DImode
+		 || GET_MODE (operands[1]) == DImode);
+
+     arm_compare_op0 = operands[0];
+     arm_compare_op1 = operands[1];
+     DONE;
+   }")
+
 ;; Cirrus SF compare instruction
 (define_insn "*cirrus_cmpsf"
   [(set (reg:CCFP CC_REGNUM)
@@ -8043,17 +8147,6 @@
    (set_attr "cirrus" "compare")]
 )
 
-;; Cirrus DI compare instruction
-(define_expand "cmpdi"
-  [(match_operand:DI 0 "cirrus_fp_register" "")
-   (match_operand:DI 1 "cirrus_fp_register" "")]
-  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
-  "{
-     arm_compare_op0 = operands[0];
-     arm_compare_op1 = operands[1];
-     DONE;
-   }")
-
 (define_insn "*cirrus_cmpdi"
   [(set (reg:CC CC_REGNUM)
 	(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
@@ -8105,8 +8198,18 @@
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "TARGET_32BIT"
-  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (GET_MODE (arm_compare_op0) == DImode
+      || GET_MODE (arm_compare_op1) == DImode)
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_blt (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "ble"
   [(set (pc)
@@ -8114,8 +8217,18 @@
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "TARGET_32BIT"
-  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (GET_MODE (arm_compare_op0) == DImode
+      || GET_MODE (arm_compare_op1) == DImode)
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_bge (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "bge"
   [(set (pc)
@@ -8141,8 +8254,18 @@
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "TARGET_32BIT"
-  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (!TARGET_ARM && (GET_MODE (arm_compare_op0) == DImode
+		      || GET_MODE (arm_compare_op1) == DImode))
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_bltu (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "bleu"
   [(set (pc)
@@ -8150,8 +8273,18 @@
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "TARGET_32BIT"
-  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (!TARGET_ARM && (GET_MODE (arm_compare_op0) == DImode
+		      || GET_MODE (arm_compare_op1) == DImode))
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_bgeu (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "bgeu"
   [(set (pc)
@@ -8375,15 +8508,35 @@
   [(set (match_operand:SI 0 "s_register_operand" "")
 	(gt:SI (match_dup 1) (const_int 0)))]
   "TARGET_32BIT && !TARGET_NO_COND_EXEC"
-  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (GET_MODE (arm_compare_op0) == DImode
+      || GET_MODE (arm_compare_op1) == DImode)
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_slt (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "sle"
   [(set (match_operand:SI 0 "s_register_operand" "")
 	(le:SI (match_dup 1) (const_int 0)))]
   "TARGET_32BIT && !TARGET_NO_COND_EXEC"
-  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (GET_MODE (arm_compare_op0) == DImode
+      || GET_MODE (arm_compare_op1) == DImode)
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_sge (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "sge"
   [(set (match_operand:SI 0 "s_register_operand" "")
@@ -8403,15 +8556,35 @@
   [(set (match_operand:SI 0 "s_register_operand" "")
 	(gtu:SI (match_dup 1) (const_int 0)))]
   "TARGET_32BIT && !TARGET_NO_COND_EXEC"
-  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (!TARGET_ARM && (GET_MODE (arm_compare_op0) == DImode
+		      || GET_MODE (arm_compare_op1) == DImode))
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_sltu (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "sleu"
   [(set (match_operand:SI 0 "s_register_operand" "")
 	(leu:SI (match_dup 1) (const_int 0)))]
   "TARGET_32BIT && !TARGET_NO_COND_EXEC"
-  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
-)
+{
+  if (!TARGET_ARM && (GET_MODE (arm_compare_op0) == DImode
+		      || GET_MODE (arm_compare_op1) == DImode))
+    {
+      rtx tem = arm_compare_op0;
+      arm_compare_op0 = arm_compare_op1;
+      arm_compare_op1 = tem;
+      emit_insn (gen_sgeu (operands[0]));
+      DONE;
+    }
+  operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
+})
 
 (define_expand "sgeu"
   [(set (match_operand:SI 0 "s_register_operand" "")
@@ -8734,6 +8907,16 @@
     if (code == UNEQ || code == LTGT)
       FAIL;
 
+    if ((code == GT || code == LE)
+	&& (GET_MODE (arm_compare_op0) == DImode
+	    || GET_MODE (arm_compare_op1) == DImode))
+      {
+	rtx tem = arm_compare_op0;
+	arm_compare_op0 = arm_compare_op1;
+	arm_compare_op1 = tem;
+	code = swap_condition (code);
+      }
+
     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
   }"
@@ -8753,6 +8936,16 @@
     if (code == UNEQ || code == LTGT)
       FAIL;
 
+    if ((code == GT || code == LE)
+	&& (GET_MODE (arm_compare_op0) == DImode
+	    || GET_MODE (arm_compare_op1) == DImode))
+      {
+	rtx tem = arm_compare_op0;
+	arm_compare_op0 = arm_compare_op1;
+	arm_compare_op1 = tem;
+	code = swap_condition (code);
+      }
+
     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
        Otherwise, ensure it is a valid FP add operand */
     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
@@ -8778,6 +8971,16 @@
     if (code == UNEQ || code == LTGT)
       FAIL;
 
+    if ((code == GT || code == LE)
+	&& (GET_MODE (arm_compare_op0) == DImode
+	    || GET_MODE (arm_compare_op1) == DImode))
+      {
+	rtx tem = arm_compare_op0;
+	arm_compare_op0 = arm_compare_op1;
+	arm_compare_op1 = tem;
+	code = swap_condition (code);
+      }
+
     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
   }"
@@ -8927,12 +9130,16 @@
    (set_attr "type" "call")]
 )
 
+;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
+;; considered a function call by the branch predictor of some cores (PR40887).
+;; Falls back to blx rN (*call_reg_armv5).
+
 (define_insn "*call_mem"
   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
 	 (match_operand 1 "" ""))
    (use (match_operand 2 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_ARM"
+  "TARGET_ARM && !arm_arch5"
   "*
   return output_call_mem (operands);
   "
@@ -9034,13 +9241,15 @@
    (set_attr "type" "call")]
 )
 
+;; Note: see *call_mem.
+
 (define_insn "*call_value_mem"
   [(set (match_operand 0 "" "")
 	(call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
 	      (match_operand 2 "" "")))
    (use (match_operand 3 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
+  "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
   "*
   return output_call_mem (&operands[1]);
   "
@@ -9089,7 +9298,7 @@
 	 (match_operand 1 "" ""))
    (use (match_operand 2 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_ARM
+  "TARGET_32BIT
    && (GET_CODE (operands[0]) == SYMBOL_REF)
    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
   "*
@@ -9105,7 +9314,7 @@
 	(match_operand:SI 2 "" "")))
    (use (match_operand 3 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_ARM
+  "TARGET_32BIT
    && (GET_CODE (operands[1]) == SYMBOL_REF)
    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
   "*
@@ -9120,7 +9329,7 @@
 	 (match_operand:SI 1 "" ""))
    (use (match_operand 2 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_THUMB
+  "TARGET_THUMB1
    && GET_CODE (operands[0]) == SYMBOL_REF
    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
   "bl\\t%a0"
@@ -9134,7 +9343,7 @@
 	      (match_operand 2 "" "")))
    (use (match_operand 3 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_THUMB
+  "TARGET_THUMB1
    && GET_CODE (operands[1]) == SYMBOL_REF
    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
   "bl\\t%a1"
@@ -9148,7 +9357,7 @@
 		    (match_operand 1 "general_operand" ""))
 	      (return)
 	      (use (match_operand 2 "" ""))])]
-  "TARGET_ARM"
+  "TARGET_32BIT"
   "
   {
     if (operands[2] == NULL_RTX)
@@ -9162,7 +9371,7 @@
 			 (match_operand 2 "general_operand" "")))
 	      (return)
 	      (use (match_operand 3 "" ""))])]
-  "TARGET_ARM"
+  "TARGET_32BIT"
   "
   {
     if (operands[3] == NULL_RTX)
@@ -9175,7 +9384,7 @@
 	(match_operand 1 "" ""))
   (return)
   (use (match_operand 2 "" ""))]
-  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
+  "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
   "*
   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
   "
@@ -9188,15 +9397,20 @@
 	     (match_operand 2 "" "")))
   (return)
   (use (match_operand 3 "" ""))]
-  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
+  "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
   "*
   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
   "
   [(set_attr "type" "call")]
 )
 
+(define_expand "return"
+  [(return)]
+  "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
+  "")
+
 ;; Often the return insn will be the same as loading from memory, so set attr
-(define_insn "return"
+(define_insn "*arm_return"
   [(return)]
   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
   "*
@@ -9213,6 +9427,19 @@
    (set_attr "predicable" "yes")]
 )
 
+;; Note: this is not predicable, to avoid issues with linker-generated
+;; interworking stubs.
+(define_insn "*thumb2_return"
+  [(return)]
+  "TARGET_THUMB2 && USE_RETURN_INSN (FALSE)"
+  "*
+  {
+    return output_return_instruction (const_true_rtx, TRUE, FALSE);
+  }"
+  [(set_attr "type" "load1")
+   (set_attr "length" "12")]
+)
+
 (define_insn "*cond_return"
   [(set (pc)
         (if_then_else (match_operator 0 "arm_comparison_operator"
diff -Naur a/src/gcc/config/arm/arm-modes.def b/src/gcc/config/arm/arm-modes.def
--- a/src/gcc/config/arm/arm-modes.def	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/arm-modes.def	2010-03-30 10:39:38.000000000 +0300
@@ -35,10 +35,16 @@
    CC_NOOVmode should be used with SImode integer equalities.
    CC_Zmode should be used if only the Z flag is set correctly
    CC_Nmode should be used if only the N (sign) flag is set correctly
+   CC_CZmode should be used if only the C and Z flags are correct
+   (used for DImode unsigned comparisons).
+   CC_NCVmode should be used if only the N, C, and V flags are correct
+   (used for DImode signed comparisons).
    CCmode should be used otherwise.  */
 
 CC_MODE (CC_NOOV);
 CC_MODE (CC_Z);
+CC_MODE (CC_CZ);
+CC_MODE (CC_NCV);
 CC_MODE (CC_SWP);
 CC_MODE (CCFP);
 CC_MODE (CCFPE);
diff -Naur a/src/gcc/config/arm/arm-protos.h b/src/gcc/config/arm/arm-protos.h
--- a/src/gcc/config/arm/arm-protos.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/arm-protos.h	2010-03-30 10:39:38.000000000 +0300
@@ -1,6 +1,7 @@
-/* Prototypes for exported functions defined in arm.c and pe.c
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+/* Prototypes for exported functions defined in arm.c, pe.c,
+   pe-cxx and pe-stubs.c.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009 Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rearnsha@arm.com)
    Minor hacks by Nick Clifton (nickc@cygnus.com)
 
@@ -42,6 +43,8 @@
 extern unsigned int arm_dbx_register_number (unsigned int);
 extern void arm_output_fn_unwind (FILE *, bool);
   
+extern int arm_major_arch (void);
+extern bool arm_thumb_arch_p (void);
 
 #ifdef RTX_CODE
 extern bool arm_vector_mode_supported_p (enum machine_mode);
@@ -49,8 +52,7 @@
 extern int const_ok_for_arm (HOST_WIDE_INT);
 extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
 			       HOST_WIDE_INT, rtx, rtx, int);
-extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
-					     rtx *);
+extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
 extern int legitimate_pic_operand_p (rtx);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
 extern rtx legitimize_tls_address (rtx, rtx);
@@ -72,6 +74,7 @@
 					  enum machine_mode, int, int);
 extern void neon_pairwise_reduce (rtx, rtx, enum machine_mode,
 				  rtx (*) (rtx, rtx, rtx));
+extern rtx neon_make_constant (rtx);
 extern void neon_expand_vector_init (rtx, rtx);
 extern void neon_lane_bounds (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 extern void neon_const_bounds (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
@@ -119,6 +122,7 @@
 extern void arm_reload_out_hi (rtx *);
 extern int arm_const_double_inline_cost (rtx);
 extern bool arm_const_double_by_parts (rtx);
+extern bool arm_const_double_by_immediates (rtx);
 extern const char *fp_immediate_constant (rtx);
 extern void arm_emit_call_insn (rtx, rtx);
 extern const char *output_call (rtx *);
@@ -196,6 +200,11 @@
 extern int arm_dllexport_name_p (const char *);
 extern int arm_dllimport_name_p (const char *);
 
+/* In pe-cxx.c and pe-stubs.c  */
+extern void arm_pe_adjust_class_at_definition (tree);
+extern bool arm_pe_type_dllimport_p (tree);
+extern bool arm_pe_type_dllexport_p (tree);
+
 #ifdef TREE_CODE
 extern void arm_pe_unique_section (tree, int);
 extern void arm_pe_encode_section_info (tree, rtx, int);
diff -Naur a/src/gcc/config/arm/arm-tune.md b/src/gcc/config/arm/arm-tune.md
--- a/src/gcc/config/arm/arm-tune.md	2009-10-12 21:26:08.000000000 +0300
+++ b/src/gcc/config/arm/arm-tune.md	2010-03-30 10:39:38.000000000 +0300
@@ -1,5 +1,5 @@
 ;; -*- buffer-read-only: t -*-
 ;; Generated automatically by gentune.sh from arm-cores.def
 (define_attr "tune"
-	"arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,marvell_f,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,cortexa5,cortexa8,cortexa9,cortexr4,cortexr4f,cortexm3,cortexm1,cortexm0"
+	"arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,marvell_f,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,cortexa5,cortexa8,cortexa9,cortexr4,cortexr4f,cortexm4,cortexm3,cortexm1,cortexm0"
 	(const (symbol_ref "arm_tune")))
diff -Naur a/src/gcc/config/arm/bpabi.h b/src/gcc/config/arm/bpabi.h
--- a/src/gcc/config/arm/bpabi.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/bpabi.h	2010-04-08 10:44:38.000000000 +0300
@@ -26,6 +26,7 @@
 #define TARGET_BPABI (TARGET_AAPCS_BASED)
 
 /* BPABI targets use EABI frame unwinding tables.  */
+#define DWARF2_UNWIND_INFO 0
 #define TARGET_UNWIND_INFO 1
 
 /* Section 4.1 of the AAPCS requires the use of VFP format.  */
diff -Naur a/src/gcc/config/arm/constraints.md b/src/gcc/config/arm/constraints.md
--- a/src/gcc/config/arm/constraints.md	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/constraints.md	2010-03-30 10:39:38.000000000 +0300
@@ -29,8 +29,9 @@
 ;; in Thumb-1 state: I, J, K, L, M, N, O
 
 ;; The following multi-letter normal constraints have been used:
-;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy
+;; in ARM/Thumb-2 state: D0, Da, Db, Dc, Di, Dn, Dl, DL, Dv, Dy
 ;; in Thumb-1 state: Pa, Pb
+;; in Thumb-2 state: Ps, Pt, Pu
 
 ;; The following memory constraints have been used:
 ;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us
@@ -147,6 +148,21 @@
        (match_test "TARGET_THUMB1 && ival >= -262 && ival <= 262
 		    && (ival > 255 || ival < -255)")))
 
+(define_constraint "Ps"
+  "@internal In Thumb-2 state a constant in the range -255 to +255"
+  (and (match_code "const_int")
+       (match_test "TARGET_THUMB2 && ival >= -255 && ival <= 255")))
+
+(define_constraint "Pt"
+  "@internal In Thumb-2 state a constant in the range -7 to +7"
+  (and (match_code "const_int")
+       (match_test "TARGET_THUMB2 && ival >= -7 && ival <= 7")))
+
+(define_constraint "Pu"
+  "@internal In Thumb-2 state a constant in the range -255 to 0"
+  (and (match_code "const_int")
+       (match_test "TARGET_THUMB2 && ival >= -255 && ival <= 0")))
+
 (define_constraint "G"
  "In ARM/Thumb-2 state a valid FPA immediate constant."
  (and (match_code "const_double")
@@ -157,6 +173,13 @@
  (and (match_code "const_double")
       (match_test "TARGET_32BIT && neg_const_double_rtx_ok_for_fpa (op)")))
 
+(define_constraint "D0"
+ "@internal
+  In ARM/Thumb-2 state a 0.0 floating point constant which can
+  be loaded with a Neon vmov immediate instruction."
+ (and (match_code "const_double")
+      (match_test "TARGET_NEON && op == CONST0_RTX (mode)")))
+
 (define_constraint "Da"
  "@internal
   In ARM/Thumb-2 state a const_int, const_double or const_vector that can
@@ -180,6 +203,13 @@
       (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
 		   && !(optimize_size || arm_ld_sched)")))
 
+(define_constraint "Di"
+ "@internal
+  In ARM/Thumb-2 state a const_int or const_double where both the high
+  and low SImode words can be generated as immediates in 32-bit instructions."
+ (and (match_code "const_double,const_int")
+      (match_test "TARGET_32BIT && arm_const_double_by_immediates (op)")))
+
 (define_constraint "Dn"
  "@internal
   In ARM/Thumb-2 state a const_vector which can be loaded with a Neon vmov
diff -Naur a/src/gcc/config/arm/cortex-a5.md b/src/gcc/config/arm/cortex-a5.md
--- a/src/gcc/config/arm/cortex-a5.md	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/cortex-a5.md	2010-04-13 10:45:12.000000000 +0300
@@ -0,0 +1,310 @@
+;; ARM Cortex-A5 pipeline description
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by CodeSourcery.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_automaton "cortex_a5")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Functional units.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The integer (ALU) pipeline.  There are five DPU pipeline stages. However the
+;; decode/issue stages operate the same for all instructions, so do not model
+;; them.  We only need to model the first execute stage because instructions
+;; always advance one stage per cycle in order. Only branch instructions may
+;; dual-issue, so a single unit  covers all of the LS, ALU, MAC and FPU
+;; pipelines.
+
+(define_cpu_unit "cortex_a5_ex1" "cortex_a5")
+
+;; The branch pipeline.  Branches can dual-issue with other instructions
+;; (except when those instructions take multiple cycles to issue).
+
+(define_cpu_unit "cortex_a5_branch" "cortex_a5")
+
+;; Pseudo-unit for blocking the multiply pipeline when a double-precision
+;; multiply is in progress.
+
+(define_cpu_unit "cortex_a5_fpmul_pipe" "cortex_a5")
+
+;; The floating-point add pipeline (ex1/f1 stage), used to model the usage
+;; of the add pipeline by fmac instructions, etc.
+
+(define_cpu_unit "cortex_a5_fpadd_pipe" "cortex_a5")
+
+;; Floating-point div/sqrt (long latency, out-of-order completion).
+
+(define_cpu_unit "cortex_a5_fp_div_sqrt" "cortex_a5")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ALU instructions.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn_reservation "cortex_a5_alu" 2
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "alu"))
+  "cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_alu_shift" 2
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "alu_shift,alu_shift_reg"))
+  "cortex_a5_ex1")
+
+;; Forwarding path for unshifted operands.
+
+(define_bypass 1 "cortex_a5_alu,cortex_a5_alu_shift"
+  "cortex_a5_alu")
+
+(define_bypass 1 "cortex_a5_alu,cortex_a5_alu_shift"
+  "cortex_a5_alu_shift"
+  "arm_no_early_alu_shift_dep")
+
+;; The multiplier pipeline can forward results from wr stage only (so I don't
+;; think there's any need to specify bypasses).
+
+(define_insn_reservation "cortex_a5_mul" 2
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "mult"))
+  "cortex_a5_ex1")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Load/store instructions.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Address-generation happens in the issue stage, which is one stage behind
+;; the ex1 stage (the first stage we care about for scheduling purposes). The
+;; dc1 stage is parallel with ex1, dc2 with ex2 and rot with wr.
+
+;; FIXME: These might not be entirely accurate for load2, load3, load4. I think
+;; they make sense since there's a 32-bit interface between the DPU and the DCU,
+;; so we can't load more than that per cycle.  The store2, store3, store4
+;; reservations are similarly guessed.
+
+(define_insn_reservation "cortex_a5_load1" 2
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "load_byte,load1"))
+  "cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_store1" 0
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "store1"))
+  "cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_load2" 3
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "load2"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_store2" 0
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "store2"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_load3" 4
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "load3"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1+cortex_a5_branch,\
+   cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_store3" 0
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "store3"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1+cortex_a5_branch,\
+   cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_load4" 5
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "load3"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1+cortex_a5_branch,\
+   cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_store4" 0
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "store3"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1+cortex_a5_branch,\
+   cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Branches.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Direct branches are the only instructions we can dual-issue (also IT and
+;; nop, but those aren't very interesting for scheduling).  (The latency here
+;; is meant to represent when the branch actually takes place, but may not be
+;; entirely correct.)
+
+(define_insn_reservation "cortex_a5_branch" 3
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "branch,call"))
+  "cortex_a5_branch")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Floating-point arithmetic.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn_reservation "cortex_a5_fpalu" 4
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "ffariths, fadds, ffarithd, faddd, fcpys, fmuls, f_cvt,\
+			fcmps, fcmpd"))
+  "cortex_a5_ex1+cortex_a5_fpadd_pipe")
+
+;; For fconsts and fconstd, 8-bit immediate data is passed directly from
+;; f1 to f3 (which I think reduces the latency by one cycle).
+
+(define_insn_reservation "cortex_a5_fconst" 3
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fconsts,fconstd"))
+  "cortex_a5_ex1+cortex_a5_fpadd_pipe")
+
+;; We should try not to attempt to issue a single-precision multiplication in
+;; the middle of a double-precision multiplication operation (the usage of
+;; cortex_a5_fpmul_pipe).
+
+(define_insn_reservation "cortex_a5_fpmuls" 4
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fmuls"))
+  "cortex_a5_ex1+cortex_a5_fpmul_pipe")
+
+;; For single-precision multiply-accumulate, the add (accumulate) is issued
+;; whilst the multiply is in F4.  The multiply result can then be forwarded
+;; from F5 to F1.  The issue unit is only used once (when we first start
+;; processing the instruction), but the usage of the FP add pipeline could
+;; block other instructions attempting to use it simultaneously.  We try to
+;; avoid that using cortex_a5_fpadd_pipe.
+
+(define_insn_reservation "cortex_a5_fpmacs" 8
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fmacs"))
+  "cortex_a5_ex1+cortex_a5_fpmul_pipe, nothing*3, cortex_a5_fpadd_pipe")
+
+;; Non-multiply instructions can issue in the middle two instructions of a
+;; double-precision multiply.  Note that it isn't entirely clear when a branch
+;; can dual-issue when a multi-cycle multiplication is in progress; we ignore
+;; that for now though.
+
+(define_insn_reservation "cortex_a5_fpmuld" 7
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fmuld"))
+  "cortex_a5_ex1+cortex_a5_fpmul_pipe, cortex_a5_fpmul_pipe*2,\
+   cortex_a5_ex1+cortex_a5_fpmul_pipe")
+
+(define_insn_reservation "cortex_a5_fpmacd" 11
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fmacd"))
+  "cortex_a5_ex1+cortex_a5_fpmul_pipe, cortex_a5_fpmul_pipe*2,\
+   cortex_a5_ex1+cortex_a5_fpmul_pipe, nothing*3, cortex_a5_fpadd_pipe")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Floating-point divide/square root instructions.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ??? Not sure if the 14 cycles taken for single-precision divide to complete
+;; includes the time taken for the special instruction used to collect the
+;; result to travel down the multiply pipeline, or not.  Assuming so.  (If
+;; that's wrong, the latency should be increased by a few cycles.)
+
+;; fsqrt takes one cycle less, but that is not modelled, nor is the use of the
+;; multiply pipeline to collect the divide/square-root result.
+
+(define_insn_reservation "cortex_a5_fdivs" 14
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fdivs"))
+  "cortex_a5_ex1, cortex_a5_fp_div_sqrt * 13")
+
+;; ??? Similarly for fdivd.
+
+(define_insn_reservation "cortex_a5_fdivd" 29
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "fdivd"))
+  "cortex_a5_ex1, cortex_a5_fp_div_sqrt * 28")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; VFP to/from core transfers.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; FP loads take data from wr/rot/f3.  Might need to define bypasses to model
+;; this?
+
+;; Core-to-VFP transfers use the multiply pipeline.
+;; Not sure about this at all... I think we need some bypasses too.
+
+(define_insn_reservation "cortex_a5_r2f" 4
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "r_2_f"))
+  "cortex_a5_ex1")
+
+;; Not sure about this either. 6.8.7 says "Additionally, the store pipe used
+;; for store and FP->core register transfers can forward into the F2 and F3
+;; stages."
+;; This doesn't correspond to what we have though.
+
+(define_insn_reservation "cortex_a5_f2r" 2
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "f_2_r"))
+  "cortex_a5_ex1")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; VFP flag transfer.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ??? The flag forwarding described in section 6.8.11 of the Cortex-A5 DPU
+;; specification (from fmstat to the ex2 stage of the second instruction) is
+;; not modeled at present.
+
+(define_insn_reservation "cortex_a5_f_flags" 4
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "f_flag"))
+  "cortex_a5_ex1")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; VFP load/store.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn_reservation "cortex_a5_f_loads" 4
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "f_loads"))
+  "cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_f_loadd" 5
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "f_load,f_loadd"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_f_stores" 0
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "f_stores"))
+  "cortex_a5_ex1")
+
+(define_insn_reservation "cortex_a5_f_stored" 0
+  (and (eq_attr "tune" "cortexa5")
+       (eq_attr "type" "f_store,f_stored"))
+  "cortex_a5_ex1+cortex_a5_branch, cortex_a5_ex1")
+
+;; Load-to-use for floating-point values has a penalty of one cycle, i.e. a
+;; latency of two (6.8.3).
+
+(define_bypass 2 "cortex_a5_f_loads"
+                 "cortex_a5_fpalu, cortex_a5_fpmacs, cortex_a5_fpmuld,\
+		  cortex_a5_fpmacd, cortex_a5_fdivs, cortex_a5_fdivd,\
+		  cortex_a5_f2r")
+
+(define_bypass 3 "cortex_a5_f_loadd"
+                 "cortex_a5_fpalu, cortex_a5_fpmacs, cortex_a5_fpmuld,\
+		  cortex_a5_fpmacd, cortex_a5_fdivs, cortex_a5_fdivd,\
+		  cortex_a5_f2r")
diff -Naur a/src/gcc/config/arm/cortex-a9.md b/src/gcc/config/arm/cortex-a9.md
--- a/src/gcc/config/arm/cortex-a9.md	2009-10-12 21:21:04.000000000 +0300
+++ b/src/gcc/config/arm/cortex-a9.md	2010-03-30 10:39:38.000000000 +0300
@@ -1,6 +1,8 @@
-;; ARM Cortex-A9 VFP pipeline description
-;; Copyright (C) 2008 Free Software Foundation, Inc.
-;; Written by CodeSourcery.
+;; ARM Cortex-A9 pipeline description
+;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+;; Originally written by CodeSourcery for VFP.
+;;
+;; Integer core pipeline description contributed by ARM Ltd.
 ;;
 ;; This file is part of GCC.
 ;;
@@ -20,9 +22,181 @@
 
 (define_automaton "cortex_a9")
 
-;; FIXME: We model a single pipeline for all instructions.
-;; Is dual-issue possible, and do we have other pipelines?
-(define_cpu_unit "cortex_a9_vfp" "cortex_a9")
+;; The Cortex-A9 integer core is modelled as a dual issue pipeline that has
+;; the following components.
+;; 1. 1 Load Store Pipeline.
+;; 2. P0 / main pipeline for data processing instructions.
+;; 3. P1 / Dual pipeline for Data processing instructions.
+;; 4. MAC pipeline for multiply as well as multiply
+;;    and accumulate instructions.
+;; 5. 1 VFP / Neon pipeline.
+;; The Load/Store and VFP/Neon pipeline are multiplexed.
+;; The P0 / main pipeline and M1 stage of the MAC pipeline are
+;;   multiplexed.
+;; The P1 / dual pipeline and M2 stage of the MAC pipeline are
+;;   multiplexed.
+;; There are only 4 register read ports and hence at any point of
+;; time we can't have issues down the E1 and the E2 ports unless
+;; of course there are bypass paths that get exercised.
+;; Both P0 and P1 have 2 stages E1 and E2.
+;; Data processing instructions issue to E1 or E2 depending on
+;; whether they have an early shift or not.
+
+
+(define_cpu_unit "cortex_a9_vfp, cortex_a9_ls" "cortex_a9")
+(define_cpu_unit "cortex_a9_p0_e1, cortex_a9_p0_e2" "cortex_a9")
+(define_cpu_unit "cortex_a9_p1_e1, cortex_a9_p1_e2" "cortex_a9")
+(define_cpu_unit "cortex_a9_p0_wb, cortex_a9_p1_wb" "cortex_a9")
+(define_cpu_unit "cortex_a9_mac_m1, cortex_a9_mac_m2" "cortex_a9")
+(define_cpu_unit "cortex_a9_branch, cortex_a9_issue_branch" "cortex_a9")
+
+(define_reservation "cortex_a9_p0_default" "cortex_a9_p0_e2, cortex_a9_p0_wb")
+(define_reservation "cortex_a9_p1_default" "cortex_a9_p1_e2, cortex_a9_p1_wb")
+(define_reservation "cortex_a9_p0_shift" "cortex_a9_p0_e1, cortex_a9_p0_default")
+(define_reservation "cortex_a9_p1_shift" "cortex_a9_p1_e1, cortex_a9_p1_default")
+
+(define_reservation "cortex_a9_multcycle1"
+  "cortex_a9_p0_e2 + cortex_a9_mac_m1 + cortex_a9_mac_m2 + \
+cortex_a9_p1_e2 + cortex_a9_p0_e1 + cortex_a9_p1_e1")
+
+(define_reservation "cortex_a9_mult16"
+  "cortex_a9_mac_m1, cortex_a9_mac_m2, cortex_a9_p0_wb")
+(define_reservation "cortex_a9_mac16"
+  "cortex_a9_multcycle1, cortex_a9_mac_m2, cortex_a9_p0_wb")
+(define_reservation "cortex_a9_mult"
+  "cortex_a9_mac_m1*2, cortex_a9_mac_m2, cortex_a9_p0_wb")
+(define_reservation "cortex_a9_mac"
+  "cortex_a9_multcycle1*2 ,cortex_a9_mac_m2, cortex_a9_p0_wb")
+
+
+;; Issue at the same time along the load store pipeline and
+;; the VFP / Neon pipeline is not possible.
+;; FIXME:: At some point we need to model the issue
+;; of the load store and the vfp being shared rather than anything else.
+
+(exclusion_set "cortex_a9_ls" "cortex_a9_vfp")
+
+
+;; Default data processing instruction without any shift
+;; The only exception to this is the mov instruction
+;; which can go down E2 without any problem.
+(define_insn_reservation "cortex_a9_dp" 2
+  (and (eq_attr "tune" "cortexa9")
+       (ior (eq_attr "type" "alu")
+	    (and (eq_attr "type" "alu_shift_reg, alu_shift")
+		 (eq_attr "insn" "mov"))))
+  "cortex_a9_p0_default|cortex_a9_p1_default")
+
+;; An instruction using the shifter will go down E1.
+(define_insn_reservation "cortex_a9_dp_shift" 3
+   (and (eq_attr "tune" "cortexa9")
+	(and (eq_attr "type" "alu_shift_reg, alu_shift")
+	     (not (eq_attr "insn" "mov"))))
+   "cortex_a9_p0_shift | cortex_a9_p1_shift")
+
+;; Loads have a latency of 4 cycles.
+;; We don't model autoincrement instructions. These
+;; instructions use the load store pipeline and 1 of
+;; the E2 units to write back the result of the increment.
+
+(define_insn_reservation "cortex_a9_load1_2" 4
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "type" "load1, load2, load_byte"))
+  "cortex_a9_ls")
+
+;; Loads multiples and store multiples can't be issued for 2 cycles in a
+;; row. The description below assumes that addresses are 64 bit aligned.
+;; If not, there is an extra cycle latency which is not modelled.
+
+;; FIXME:: This bit might need to be reworked when we get to
+;; tuning for the VFP because strictly speaking the ldm
+;; is sent to the LSU unit as is and there is only an
+;; issue restriction between the LSU and the VFP/ Neon unit.
+
+(define_insn_reservation "cortex_a9_load3_4" 5
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "type" "load3, load4"))
+  "cortex_a9_ls, cortex_a9_ls")
+
+(define_insn_reservation "cortex_a9_store1_2" 0
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "type" "store1, store2"))
+  "cortex_a9_ls")
+
+;; Almost all our store multiples use an auto-increment
+;; form. Don't issue back to back load and store multiples
+;; because the load store unit will stall.
+(define_insn_reservation "cortex_a9_store3_4" 0
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "type" "store3, store4"))
+  "cortex_a9_ls+(cortex_a9_p0_default | cortex_a9_p1_default), cortex_a9_ls")
+
+;; We get 16*16 multiply / mac results in 3 cycles.
+(define_insn_reservation "cortex_a9_mult16" 3
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "insn" "smulxy"))
+       "cortex_a9_mult16")
+
+;; The 16*16 mac is slightly different that it
+;; reserves M1 and M2 in the same cycle.
+(define_insn_reservation "cortex_a9_mac16" 3
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "insn" "smlaxy"))
+  "cortex_a9_mac16")
+
+
+(define_insn_reservation "cortex_a9_multiply" 4
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "insn" "mul"))
+       "cortex_a9_mult")
+
+(define_insn_reservation "cortex_a9_mac" 4
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "insn" "mla"))
+       "cortex_a9_mac")
+
+;; An instruction with a result in E2 can be forwarded
+;; to E2 or E1 or M1 or the load store unit in the next cycle.
+
+(define_bypass 1 "cortex_a9_dp"
+                 "cortex_a9_dp_shift, cortex_a9_multiply,
+ cortex_a9_load1_2, cortex_a9_dp, cortex_a9_store1_2,
+ cortex_a9_mult16, cortex_a9_mac16, cortex_a9_mac, cortex_a9_store3_4, cortex_a9_load3_4")
+
+(define_bypass 2 "cortex_a9_dp_shift"
+                 "cortex_a9_dp_shift, cortex_a9_multiply,
+ cortex_a9_load1_2, cortex_a9_dp, cortex_a9_store1_2,
+ cortex_a9_mult16, cortex_a9_mac16, cortex_a9_mac, cortex_a9_store3_4, cortex_a9_load3_4")
+
+;; An instruction in the load store pipeline can provide
+;; read access to a DP instruction in the P0 default pipeline
+;; before the writeback stage.
+
+(define_bypass 3 "cortex_a9_load1_2" "cortex_a9_dp, cortex_a9_load1_2,
+cortex_a9_store3_4, cortex_a9_store1_2")
+
+(define_bypass 4 "cortex_a9_load3_4" "cortex_a9_dp, cortex_a9_load1_2,
+cortex_a9_store3_4, cortex_a9_store1_2,  cortex_a9_load3_4")
+
+;; Calls and branches.
+
+;; Branch instructions
+
+(define_insn_reservation "cortex_a9_branch" 0
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "type" "branch"))
+  "cortex_a9_branch")
+
+;; Call latencies are essentially 0 but make sure
+;; dual issue doesn't happen i.e the next instruction
+;; starts at the next cycle.
+(define_insn_reservation "cortex_a9_call"  0
+  (and (eq_attr "tune" "cortexa9")
+       (eq_attr "type" "call"))
+  "cortex_a9_issue_branch + cortex_a9_multcycle1 + cortex_a9_ls + cortex_a9_vfp")
+
+
+;; Pipelining for VFP instructions.
 
 (define_insn_reservation "cortex_a9_ffarith" 1
  (and (eq_attr "tune" "cortexa9")
diff -Naur a/src/gcc/config/arm/cygming.opt b/src/gcc/config/arm/cygming.opt
--- a/src/gcc/config/arm/cygming.opt	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/cygming.opt	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,36 @@
+; Cygwin- and MinGW-specific options.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+mcygwin
+Target
+Use the Cygwin interface
+
+; ### TODO make this work.
+; mnop-fun-dllimport
+; Target Report Var(TARGET_NOP_FUN_DLLIMPORT)
+; Ignore dllimport for functions
+
+mthreads
+Target RejectNegative
+Use Mingw-specific thread support
+
+mwin32
+Target
+Set Windows defines
diff -Naur a/src/gcc/config/arm/eabi-memcpy.c b/src/gcc/config/arm/eabi-memcpy.c
--- a/src/gcc/config/arm/eabi-memcpy.c	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/eabi-memcpy.c	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,108 @@
+/* Simple implementation of memcpy/memmove for targets that don't provide
+   their own.
+
+   copyright (c) 2010  free software foundation, inc.
+   contributed by codesourcery.
+
+   this file is free software; you can redistribute it and/or modify it
+   under the terms of the gnu general public license as published by the
+   free software foundation; either version 3, or (at your option) any
+   later version.
+
+   this file is distributed in the hope that it will be useful, but
+   without any warranty; without even the implied warranty of
+   merchantability or fitness for a particular purpose.  see the gnu
+   general public license for more details.
+
+   under section 7 of gpl version 3, you are granted additional
+   permissions described in the gcc runtime library exception, version
+   3.1, as published by the free software foundation.
+
+   you should have received a copy of the gnu general public license and
+   a copy of the gcc runtime library exception along with this program;
+   see the files copying3 and copying.runtime respectively.  if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+
+/* Define ALIASNAME as a strong alias for NAME.  */
+#define strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
+/* Nonzero if either X or Y is not aligned on a "long" boundary.  */
+#define UNALIGNED(X, Y) \
+  (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+
+/* How many bytes are copied each iteration of the 4X unrolled loop.  */
+#define BIGBLOCKSIZE    (sizeof (long) << 2)
+
+/* How many bytes are copied each iteration of the word copy loop.  */
+#define LITTLEBLOCKSIZE (sizeof (long))
+
+/* Threshhold for punting to the byte copier.  */
+#define TOO_SMALL(LEN)  ((LEN) < BIGBLOCKSIZE)
+
+void
+__aeabi_memcpy (void *dst0, const void *src0, unsigned long len)
+{
+  char *dst = dst0;
+  const char *src = src0;
+  long *aligned_dst;
+  const long *aligned_src;
+
+  /* If the size is small, or either SRC or DST is unaligned,
+     then punt into the byte copy loop.  This should be rare.  */
+  if (!TOO_SMALL(len) && !UNALIGNED (src, dst))
+    {
+      aligned_dst = (long *)dst;
+      aligned_src = (const long *)src;
+
+      /* Copy 4X long words at a time if possible.  */
+      while (len >= BIGBLOCKSIZE)
+        {
+          *aligned_dst++ = *aligned_src++;
+          *aligned_dst++ = *aligned_src++;
+          *aligned_dst++ = *aligned_src++;
+          *aligned_dst++ = *aligned_src++;
+          len -= BIGBLOCKSIZE;
+        }
+
+      /* Copy one long word at a time if possible.  */
+      while (len >= LITTLEBLOCKSIZE)
+        {
+          *aligned_dst++ = *aligned_src++;
+          len -= LITTLEBLOCKSIZE;
+        }
+
+       /* Pick up any residual with a byte copier.  */
+      dst = (char *)aligned_dst;
+      src = (const char *)aligned_src;
+    }
+
+  while (len--)
+    *dst++ = *src++;
+}
+
+void
+__aeabi_memmove (void *dst_void, const void *src_void, unsigned long len)
+{
+  char *dst = dst_void;
+  const char *src = src_void;
+
+  if (src < dst && dst < src + len)
+    {
+      /* Destructive overlap...have to copy backwards */
+      src += len;
+      dst += len;
+      while (len--)
+	{
+	  *--dst = *--src;
+	}
+    }
+  else
+    __aeabi_memcpy (dst_void, src_void, len);
+}
+
+strong_alias(__aeabi_memcpy, __aeabi_memcpy4)
+strong_alias(__aeabi_memcpy, __aeabi_memcpy8)
+strong_alias(__aeabi_memmove, __aeabi_memmove4)
+strong_alias(__aeabi_memmove, __aeabi_memmove8)
diff -Naur a/src/gcc/config/arm/eabi-memset.c b/src/gcc/config/arm/eabi-memset.c
--- a/src/gcc/config/arm/eabi-memset.c	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/eabi-memset.c	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,97 @@
+/* Simple implementation of memset/memclr for targets that don't provide
+   their own.
+
+   copyright (c) 2010  free software foundation, inc.
+   contributed by codesourcery.
+
+   this file is free software; you can redistribute it and/or modify it
+   under the terms of the gnu general public license as published by the
+   free software foundation; either version 3, or (at your option) any
+   later version.
+
+   this file is distributed in the hope that it will be useful, but
+   without any warranty; without even the implied warranty of
+   merchantability or fitness for a particular purpose.  see the gnu
+   general public license for more details.
+
+   under section 7 of gpl version 3, you are granted additional
+   permissions described in the gcc runtime library exception, version
+   3.1, as published by the free software foundation.
+
+   you should have received a copy of the gnu general public license and
+   a copy of the gcc runtime library exception along with this program;
+   see the files copying3 and copying.runtime respectively.  if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+
+/* Define ALIASNAME as a strong alias for NAME.  */
+#define strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
+#define LBLOCKSIZE (sizeof(long))
+#define UNALIGNED(X)   ((long)X & (LBLOCKSIZE - 1))
+#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
+
+void
+__aeabi_memset (void *m, unsigned long n, int c)
+{
+  char *s = (char *)m;
+  int i;
+  unsigned long buffer;
+  unsigned long *aligned_addr;
+  unsigned int d = c & 0xff;	/* To avoid sign extension, copy C to an
+				   unsigned variable.  */
+
+  while (UNALIGNED (s))
+    {
+      if (n--)
+        *s++ = (char) c;
+      else
+        return m;
+    }
+
+  if (!TOO_SMALL (n))
+    {
+      /* If we get this far, we know that n is large and s is word-aligned. */
+      aligned_addr = (unsigned long *)s;
+
+      /* Store D into each char sized location in BUFFER so that
+         we can set large blocks quickly.  */
+      buffer = (d << 8) | d;
+      buffer |= (buffer << 16);
+      for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
+        buffer = (buffer << i) | buffer;
+
+      /* Unroll the loop.  */
+      while (n >= LBLOCKSIZE * 4)
+        {
+          *aligned_addr++ = buffer;
+          *aligned_addr++ = buffer;
+          *aligned_addr++ = buffer;
+          *aligned_addr++ = buffer;
+          n -= 4 * LBLOCKSIZE;
+        }
+
+      while (n >= LBLOCKSIZE)
+        {
+          *aligned_addr++ = buffer;
+          n -= LBLOCKSIZE;
+        }
+      /* Pick up the remainder with a bytewise loop.  */
+      s = (char *)aligned_addr;
+    }
+
+  while (n--)
+    *s++ = (char) c;
+}
+
+void
+__aeabi_memclr (void *m, unsigned long n)
+{
+  __aeabi_memset (m, n, 0);
+}
+
+strong_alias(__aeabi_memset, __aeabi_memset4)
+strong_alias(__aeabi_memset, __aeabi_memset8)
+strong_alias(__aeabi_memclr, __aeabi_memclr4)
+strong_alias(__aeabi_memclr, __aeabi_memclr8)
diff -Naur a/src/gcc/config/arm/fp16.c b/src/gcc/config/arm/fp16.c
--- a/src/gcc/config/arm/fp16.c	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/fp16.c	2010-04-13 10:45:12.000000000 +0300
@@ -22,10 +22,10 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-static inline unsigned short
+static inline unsigned int
 __gnu_f2h_internal(unsigned int a, int ieee)
 {
-  unsigned short sign = (a >> 16) & 0x8000;
+  unsigned int sign = (a >> 16) & 0x8000;
   int aexp = (a >> 23) & 0xff;
   unsigned int mantissa = a & 0x007fffff;
   unsigned int mask;
@@ -95,10 +95,10 @@
   return sign | (((aexp + 14) << 10) + (mantissa >> 13));
 }
 
-unsigned int
-__gnu_h2f_internal(unsigned short a, int ieee)
+static inline unsigned int
+__gnu_h2f_internal(unsigned int a, int ieee)
 {
-  unsigned int sign = (unsigned int)(a & 0x8000) << 16;
+  unsigned int sign = (a & 0x00008000) << 16;
   int aexp = (a >> 10) & 0x1f;
   unsigned int mantissa = a & 0x3ff;
 
@@ -120,26 +120,33 @@
   return sign | (((aexp + 0x70) << 23) + (mantissa << 13));
 }
 
-unsigned short
+#define ALIAS(src, dst) \
+  typeof (src) dst __attribute__ ((alias (#src)));
+
+unsigned int
 __gnu_f2h_ieee(unsigned int a)
 {
   return __gnu_f2h_internal(a, 1);
 }
+ALIAS (__gnu_f2h_ieee, __aeabi_f2h)
 
 unsigned int
-__gnu_h2f_ieee(unsigned short a)
+__gnu_h2f_ieee(unsigned int a)
 {
   return __gnu_h2f_internal(a, 1);
 }
+ALIAS (__gnu_h2f_ieee, __aeabi_h2f)
 
-unsigned short
+unsigned int
 __gnu_f2h_alternative(unsigned int x)
 {
   return __gnu_f2h_internal(x, 0);
 }
+ALIAS (__gnu_f2h_alternative, __aeabi_f2h_alt)
 
 unsigned int
-__gnu_h2f_alternative(unsigned short a)
+__gnu_h2f_alternative(unsigned int a)
 {
   return __gnu_h2f_internal(a, 0);
 }
+ALIAS (__gnu_h2f_alternative, __aeabi_h2f_alt)
diff -Naur a/src/gcc/config/arm/lib1funcs.asm b/src/gcc/config/arm/lib1funcs.asm
--- a/src/gcc/config/arm/lib1funcs.asm	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/lib1funcs.asm	2010-03-30 10:39:38.000000000 +0300
@@ -104,7 +104,8 @@
 #endif
 
 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
-	|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
+	|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+	|| defined(__ARM_ARCH_7EM__)
 # define __ARM_ARCH__ 7
 #endif
 
@@ -1349,9 +1350,6 @@
 #define ah	r1
 #endif
 
-/* Prevent __aeabi double-word shifts from being produced on SymbianOS.  */
-#ifndef __symbian__
-
 #ifdef L_lshrdi3
 
 	FUNC_START lshrdi3
@@ -1453,8 +1451,6 @@
 
 #endif
 
-#endif /* __symbian__ */
-
 #if ((__ARM_ARCH__ > 5) && !defined(__ARM_ARCH_6M__)) \
     || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
     || defined(__ARM_ARCH_5TEJ__)
@@ -1750,7 +1746,6 @@
 #endif /* !__thumb2__ */
 #endif /* Arch supports thumb.  */
 
-#ifndef __symbian__
 #ifndef __ARM_ARCH_6M__
 #include "ieee754-df.S"
 #include "ieee754-sf.S"
@@ -1758,4 +1753,3 @@
 #else /* __ARM_ARCH_6M__ */
 #include "bpabi-v6m.S"
 #endif /* __ARM_ARCH_6M__ */
-#endif /* !__symbian__ */
diff -Naur a/src/gcc/config/arm/libunwind.S b/src/gcc/config/arm/libunwind.S
--- a/src/gcc/config/arm/libunwind.S	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/libunwind.S	2010-03-30 10:39:38.000000000 +0300
@@ -27,8 +27,6 @@
 .previous
 #endif
 
-#ifndef __symbian__
-
 #include "lib1funcs.asm"
 
 .macro UNPREFIX name
@@ -348,5 +346,3 @@
 UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
 UNWIND_WRAPPER _Unwind_ForcedUnwind 3
 UNWIND_WRAPPER _Unwind_Backtrace 2
-
-#endif  /* ndef __symbian__ */
diff -Naur a/src/gcc/config/arm/mingw32.h b/src/gcc/config/arm/mingw32.h
--- a/src/gcc/config/arm/mingw32.h	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/mingw32.h	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,140 @@
+/* Operating system specific defines to be used when targeting GCC for
+   hosting on Windows CE, using GNU tools and the Windows32 API Library.
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (arm MinGW)"); 
+
+#undef EXTRA_OS_CPP_BUILTINS
+#define EXTRA_OS_CPP_BUILTINS()					\
+  do								\
+    {								\
+      builtin_define ("_WIN32");				\
+      builtin_define_std ("WIN32");				\
+      builtin_define_std ("WINNT");				\
+    }								\
+  while (0)
+
+#undef STANDARD_INCLUDE_DIR
+#define STANDARD_INCLUDE_DIR "/mingw/include"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} \
+-D__COREDLL__ -D__MINGW32__ -D__MINGW32CE__ -D__CEGCC_VERSION__ \
+%{!nostdinc: -idirafter ../include/w32api%s -idirafter ../../include/w32api%s }"
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{pg:-lgmon} -lcoredll"
+
+/* Include in the mingw32 libraries with libgcc */
+#undef LINK_SPEC
+#define LINK_SPEC "%{shared|mdll: --shared} \
+  %{static:-Bstatic} %{!static:-Bdynamic} \
+  %{shared|mdll: -e DllMainCRTStartup}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{shared|mdll:dllcrt3%O%s} \
+  %{!shared:%{!mdll:crt3%O%s}} %{pg:gcrt3%O%s}"
+
+/* Override startfile prefix defaults.  */
+#ifndef STANDARD_STARTFILE_PREFIX_1
+#define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib/"
+#endif
+#ifndef STANDARD_STARTFILE_PREFIX_2
+#define STANDARD_STARTFILE_PREFIX_2 ""
+#endif
+
+/* Output STRING, a string representing a filename, to FILE.
+   We canonicalize it to be in Unix format (backslashes are replaced
+   forward slashes.  */
+#undef OUTPUT_QUOTED_STRING
+#define OUTPUT_QUOTED_STRING(FILE, STRING)               \
+do {						         \
+  char c;					         \
+						         \
+  putc ('\"', asm_file);			         \
+						         \
+  while ((c = *string++) != 0)			         \
+    {						         \
+      if (c == '\\')				         \
+	c = '/';				         \
+						         \
+      if (ISPRINT (c))                                   \
+        {                                                \
+          if (c == '\"')			         \
+	    putc ('\\', asm_file);		         \
+          putc (c, asm_file);			         \
+        }                                                \
+      else                                               \
+        fprintf (asm_file, "\\%03o", (unsigned char) c); \
+    }						         \
+						         \
+  putc ('\"', asm_file);			         \
+} while (0)
+
+/*
+ * See the message from Dave Korn dated 2009/06/01 15:44 on the cegcc mailing
+ * list, and the gcc ChangeLog entry dated 2009-01-21, also by Dave.
+ *
+ * Based on that, we're replacing LIBGCC_SPEC by SHARED_LIBGCC_SPEC and
+ * REAL_GCC_SPEC. This is based on cygwin's definition, which we extend
+ * with the other libraries we need.
+ *
+ * The old definition :
+  "%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lceoldname -lmingwex -lcoredll"
+ *
+ */
+#undef LIBGCC_SPEC
+
+#undef SHARED_LIBGCC_SPEC
+#ifdef ENABLE_SHARED_LIBGCC
+#define SHARED_LIBGCC_SPEC " \
+ %{mthreads:-lmingwthrd} -lmingw32 \
+ %{static|static-libgcc:-lgcc -lgcc_eh} \
+ %{!static: \
+   %{!static-libgcc: \
+     %{!shared: \
+       %{!shared-libgcc:-lgcc -lgcc_eh} \
+       %{shared-libgcc:-lgcc_s -lgcc} \
+      } \
+     %{shared:-lgcc_s -lgcc} \
+    } \
+  } \
+  -lceoldname -lmingwex -lcoredll"
+#else
+#define SHARED_LIBGCC_SPEC \
+  "%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lceoldname -lmingwex -lcoredll"
+#endif
+
+#undef REAL_LIBGCC_SPEC
+#define REAL_LIBGCC_SPEC SHARED_LIBGCC_SPEC
+
+/* On mingw32ce, the reference chain goes like
+   WinMainCRTStartup(entry)->WinMain->main.  So,
+   libgfortranbegin.a(fmain.o:main) must be seen after
+   libmingw.a(WinMain).  */
+#define FORTRAN_INIT "-Wl,-lmingw32,-lgfortranbegin"
+
+/* Only include windows.h when needed, to avoid conflicts with
+   fp-bit.c in the definition of FLOAT.  */
+#if defined(IN_LIBGCC2) && (defined(L_trampoline))
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
diff -Naur a/src/gcc/config/arm/msformat-c.c b/src/gcc/config/arm/msformat-c.c
--- a/src/gcc/config/arm/msformat-c.c	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/msformat-c.c	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,197 @@
+/* Check calls to formatted I/O functions (-Wformat).
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "flags.h"
+#include "c-common.h"
+#include "toplev.h"
+#include "intl.h"
+#include "diagnostic.h"
+#include "langhooks.h"
+#include "c-format.h"
+#include "alloc-pool.h"
+
+/* Mingw specific format attributes ms_printf, ms_scanf, and ms_strftime.  */
+
+static format_length_info ms_printf_length_specs[] =
+{
+  { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
+  { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
+  { "I32", FMT_LEN_l, STD_EXT, NULL, 0, 0 },
+  { "I64", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
+  { "I", FMT_LEN_L, STD_EXT, NULL, 0, 0 },
+  { NULL, 0, 0, NULL, 0, 0 }
+};
+
+static const format_flag_spec ms_printf_flag_specs[] =
+{
+  { ' ',  0, 0, N_("' ' flag"),        N_("the ' ' printf flag"),              STD_C89 },
+  { '+',  0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
+  { '#',  0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
+  { '0',  0, 0, N_("'0' flag"),        N_("the '0' printf flag"),              STD_C89 },
+  { '-',  0, 0, N_("'-' flag"),        N_("the '-' printf flag"),              STD_C89 },
+  { '\'', 0, 0, N_("''' flag"),        N_("the ''' printf flag"),              STD_EXT },
+  { 'w',  0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
+  { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
+  { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
+  { 0, 0, 0, NULL, NULL, 0 }
+};
+
+static const format_flag_pair ms_printf_flag_pairs[] =
+{
+  { ' ', '+', 1, 0   },
+  { '0', '-', 1, 0   }, { '0', 'p', 1, 'i' },
+  { 0, 0, 0, 0 }
+};
+
+static const format_flag_spec ms_scanf_flag_specs[] =
+{
+  { '*',  0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
+  { 'a',  0, 0, N_("'a' flag"),               N_("the 'a' scanf flag"),                       STD_EXT },
+  { 'w',  0, 0, N_("field width"),            N_("field width in scanf format"),              STD_C89 },
+  { 'L',  0, 0, N_("length modifier"),        N_("length modifier in scanf format"),          STD_C89 },
+  { '\'', 0, 0, N_("''' flag"),               N_("the ''' scanf flag"),                       STD_EXT },
+  { 0, 0, 0, NULL, NULL, 0 }
+};
+
+static const format_flag_pair ms_scanf_flag_pairs[] =
+{
+  { '*', 'L', 0, 0 },
+  { 0, 0, 0, 0 }
+};
+
+static const format_flag_spec ms_strftime_flag_specs[] =
+{
+  { '#', 0,   0, N_("'#' flag"),     N_("the '#' strftime flag"),          STD_EXT },
+  { 0, 0, 0, NULL, NULL, 0 }
+};
+
+static const format_flag_pair ms_strftime_flag_pairs[] =
+{
+  { 0, 0, 0, 0 }
+};
+
+static const format_char_info ms_print_char_table[] =
+{
+  /* C89 conversion specifiers.  */
+  { "di",  0, STD_C89, { T89_I,   BADLEN,  T89_S,   T89_L,   T9L_LL,  T99_SST,  BADLEN, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +'",  "i",  NULL },
+  { "oxX", 0, STD_C89, { T89_UI,  BADLEN,  T89_US,  T89_UL,  T9L_ULL, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
+  { "u",   0, STD_C89, { T89_UI,  BADLEN,  T89_US,  T89_UL,  T9L_ULL, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN,  BADLEN,  BADLEN }, "-wp0'",    "i",  NULL },
+  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "",   NULL },
+  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN }, "-wp0 +#",  "",   NULL },
+  { "c",   0, STD_C89, { T89_I,   BADLEN,  T89_S,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
+  { "s",   1, STD_C89, { T89_C,   BADLEN,  T89_S,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "cR", NULL },
+  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "c",  NULL },
+  { "n",   1, STD_C89, { T89_I,   BADLEN,  T89_S,   T89_L,   T9L_LL,  BADLEN,  BADLEN, BADLEN,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "",          "W",  NULL },
+  /* X/Open conversion specifiers.  */
+  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  T89_S,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
+  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  T89_S,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "R",  NULL },
+  { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+static const format_char_info ms_scan_char_table[] =
+{
+  /* C89 conversion specifiers.  */
+  { "di",    1, STD_C89, { T89_I,   BADLEN,  T89_S,   T89_L,   T9L_LL,  T99_SST,  BADLEN, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*w'", "W",   NULL },
+  { "u",     1, STD_C89, { T89_UI,  BADLEN,  T89_US,  T89_UL,  T9L_ULL, T99_ST, BADLEN,  BADLEN, BADLEN, BADLEN,  BADLEN,  BADLEN }, "*w'", "W",   NULL },
+  { "oxX",   1, STD_C89, { T89_UI,  BADLEN,  T89_US,  T89_UL,  T9L_ULL, T99_ST, BADLEN,  BADLEN, BADLEN, BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
+  { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN }, "*w'",  "W",   NULL },
+  { "c",     1, STD_C89, { T89_C,   BADLEN,  T89_S,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*w",   "cW",  NULL },
+  { "s",     1, STD_C89, { T89_C,   BADLEN,  T89_S,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*aw",  "cW",  NULL },
+  { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*aw",  "cW[", NULL },
+  { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
+  { "n",     1, STD_C89, { T89_I,   BADLEN,  T89_S,   T89_L,   T9L_LL,  BADLEN,  BADLEN, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "",     "W",   NULL },
+  /* X/Open conversion specifiers.  */
+  { "C",     1, STD_EXT, { TEX_W,   BADLEN,  T89_S,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
+  { "S",     1, STD_EXT, { TEX_W,   BADLEN,  T89_S,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*aw",  "W",   NULL },
+  { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+static const format_char_info ms_time_char_table[] =
+{
+  /* C89 conversion specifiers.  */
+  { "ABZab",		0, STD_C89, NOLENGTHS, "#",     "",   NULL },
+  { "cx",		0, STD_C89, NOLENGTHS, "#",      "3",  NULL },
+  { "HIMSUWdmw",	0, STD_C89, NOLENGTHS, "#",  "",   NULL },
+  { "j",		0, STD_C89, NOLENGTHS, "#",  "",  NULL },
+  { "p",		0, STD_C89, NOLENGTHS, "#",      "",   NULL },
+  { "X",		0, STD_C89, NOLENGTHS, "#",      "",   NULL },
+  { "y",		0, STD_C89, NOLENGTHS, "#", "4",  NULL },
+  { "Y",		0, STD_C89, NOLENGTHS, "#", "",  NULL },
+  { "%",		0, STD_C89, NOLENGTHS, "",       "",   NULL },
+  /* C99 conversion specifiers.  */
+  { "z",		0, STD_C99, NOLENGTHS, "#",      "",  NULL },
+  { NULL,		0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+const format_kind_info mingw_format_attributes[3] =
+{
+  { "ms_printf",   ms_printf_length_specs,  ms_print_char_table, " +#0-'", NULL,
+    ms_printf_flag_specs, ms_printf_flag_pairs,
+    FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
+    'w', 0, 'p', 0, 'L', 0,
+    &integer_type_node, &integer_type_node
+  },
+  { "ms_scanf",    ms_printf_length_specs,   ms_scan_char_table,  "*'", NULL,
+    ms_scanf_flag_specs, ms_scanf_flag_pairs,
+    FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
+    'w', 0, 0, '*', 'L', 0,
+    NULL, NULL
+  },
+  { "ms_strftime", NULL,                 ms_time_char_table,  "", "#",
+    ms_strftime_flag_specs, ms_strftime_flag_pairs,
+    FMT_FLAG_FANCY_PERCENT_OK, 0, 0, 0, 0, 0, 0,
+    NULL, NULL
+  }
+};
+
+/* Default overrides for printf, scanf and strftime.  */
+const target_ovr_attr mingw_format_attribute_overrides[4] =
+{
+  { "ms_printf", "printf" },
+  { "ms_scanf", "scanf" },
+  { "ms_strftime", "strftime" }
+};
+
+/* Setup for option Wpedantic-ms-format.  */
+
+#ifdef TARGET_OVERRIDES_FORMAT_INIT
+
+/* Make sure TARGET_OVERRIDES_FORMAT_INIT is prototyped.  */
+extern void TARGET_OVERRIDES_FORMAT_INIT (void);
+
+/* Helper.  */
+#define C89_OR_EXT (warn_pedantic_ms_format ? STD_EXT : STD_C89)
+
+void
+TARGET_OVERRIDES_FORMAT_INIT (void)
+{
+  ms_printf_length_specs[2].std = C89_OR_EXT; /* I32 */
+  ms_printf_length_specs[3].std = C89_OR_EXT; /* I64 */
+  ms_printf_length_specs[4].std = C89_OR_EXT; /* I */
+}
+
+#undef C89_OR_EXT
+
+#endif
diff -Naur a/src/gcc/config/arm/neon-docgen.ml b/src/gcc/config/arm/neon-docgen.ml
--- a/src/gcc/config/arm/neon-docgen.ml	2009-10-12 21:21:04.000000000 +0300
+++ b/src/gcc/config/arm/neon-docgen.ml	2010-03-30 10:39:38.000000000 +0300
@@ -214,6 +214,7 @@
     | Element_of_dreg -> (analyze_shape_elt reg_no Dreg) ^ "[@var{0}]"
     | Element_of_qreg -> (analyze_shape_elt reg_no Qreg) ^ "[@var{0}]"
     | All_elements_of_dreg -> (analyze_shape_elt reg_no Dreg) ^ "[]"
+    | Alternatives alts -> (analyze_shape_elt reg_no (List.hd alts))
   in
     match shape with
       All (n, elt) -> commas (analyze_shape_elt 0) (n_things n elt) ""
diff -Naur a/src/gcc/config/arm/neon.md b/src/gcc/config/arm/neon.md
--- a/src/gcc/config/arm/neon.md	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/neon.md	2010-04-09 10:32:04.000000000 +0300
@@ -22,17 +22,11 @@
 (define_constants
   [(UNSPEC_ASHIFT_SIGNED	65)
    (UNSPEC_ASHIFT_UNSIGNED	66)
-   (UNSPEC_VABA			67)
-   (UNSPEC_VABAL		68)
    (UNSPEC_VABD			69)
    (UNSPEC_VABDL		70)
-   (UNSPEC_VABS			71)
-   (UNSPEC_VADD			72)
    (UNSPEC_VADDHN		73)
    (UNSPEC_VADDL		74)
    (UNSPEC_VADDW		75)
-   (UNSPEC_VAND			76)
-   (UNSPEC_VBIC			77)
    (UNSPEC_VBSL			78)
    (UNSPEC_VCAGE		79)
    (UNSPEC_VCAGT		80)
@@ -40,18 +34,9 @@
    (UNSPEC_VCGE			82)
    (UNSPEC_VCGT			83)
    (UNSPEC_VCLS			84)
-   (UNSPEC_VCLZ			85)
-   (UNSPEC_VCNT			86)
-   (UNSPEC_VCOMBINE		87)
    (UNSPEC_VCVT			88)
    (UNSPEC_VCVT_N		89)
-   (UNSPEC_VDUP_LANE		90)
-   (UNSPEC_VDUP_N		91)
-   (UNSPEC_VEOR			92)
    (UNSPEC_VEXT			93)
-   (UNSPEC_VGET_HIGH		94)
-   (UNSPEC_VGET_LANE		95)
-   (UNSPEC_VGET_LOW		96)
    (UNSPEC_VHADD		97)
    (UNSPEC_VHSUB		98)
    (UNSPEC_VLD1			99)
@@ -72,11 +57,9 @@
    (UNSPEC_VLD4_LANE		114)
    (UNSPEC_VMAX			115)
    (UNSPEC_VMIN			116)
-   (UNSPEC_VMLA			117)
    (UNSPEC_VMLAL		118)
    (UNSPEC_VMLA_LANE		119)
    (UNSPEC_VMLAL_LANE		120)
-   (UNSPEC_VMLS			121)
    (UNSPEC_VMLSL		122)
    (UNSPEC_VMLS_LANE		123)
    (UNSPEC_VMLSL_LANE		124)
@@ -86,10 +69,6 @@
    (UNSPEC_VMULL		128)
    (UNSPEC_VMUL_LANE		129)
    (UNSPEC_VMULL_LANE		130)
-   (UNSPEC_VMUL_N		131)
-   (UNSPEC_VMVN			132)
-   (UNSPEC_VORN			133)
-   (UNSPEC_VORR			134)
    (UNSPEC_VPADAL		135)
    (UNSPEC_VPADD		136)
    (UNSPEC_VPADDL		137)
@@ -125,7 +104,6 @@
    (UNSPEC_VREV64		167)
    (UNSPEC_VRSQRTE		168)
    (UNSPEC_VRSQRTS		169)
-   (UNSPEC_VSET_LANE		170)
    (UNSPEC_VSHL			171)
    (UNSPEC_VSHLL_N		172)
    (UNSPEC_VSHL_N		173)
@@ -147,7 +125,6 @@
    (UNSPEC_VST4B		189)
    (UNSPEC_VST4_LANE		190)
    (UNSPEC_VSTRUCTDUMMY		191)
-   (UNSPEC_VSUB			192)
    (UNSPEC_VSUBHN		193)
    (UNSPEC_VSUBL		194)
    (UNSPEC_VSUBW		195)
@@ -336,6 +313,14 @@
 				  (V4HI "V2SI") (V8HI "V4SI")
 				  (V2SI "DI")   (V4SI "V2DI")])
 
+;; Double-sized modes with the same element size.
+;; Used for neon_vdup_lane, where the second operand is double-sized
+;; even when the first one is quad.
+(define_mode_attr V_double_vector_mode [(V16QI "V8QI") (V8HI "V4HI")
+                                        (V4SI "V2SI") (V4SF "V2SF")
+                                        (V8QI "V8QI") (V4HI "V4HI")
+                                        (V2SI "V2SI") (V2SF "V2SF")])
+
 ;; Mode of result of comparison operations (and bit-select operand 1).
 (define_mode_attr V_cmp_result [(V8QI "V8QI") (V16QI "V16QI")
 			        (V4HI "V4HI") (V8HI  "V8HI")
@@ -712,7 +697,7 @@
 
 (define_insn "*movmisalign<mode>_neon_load"
   [(set (match_operand:VQX 0 "s_register_operand"           "=w")
-	(unspec:VQX [(match_operand:VQX 1 "general_operand" " Um")]
+	(unspec:VQX [(match_operand:VQX 1 "memory_operand"  " Um")]
 		    UNSPEC_MISALIGNED_ACCESS))]
   "TARGET_NEON && !BYTES_BIG_ENDIAN"
   "vld1.<V_sz_elem>\t{%q0}, %A1"
@@ -732,7 +717,7 @@
     elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
   operands[2] = GEN_INT (elt);
   
-  return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
+  return "vmov%?.<V_sz_elem>\t%P0[%c2], %1";
 }
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_mcr")])
@@ -758,7 +743,7 @@
   operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
   operands[2] = GEN_INT (elt);
 
-  return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
+  return "vmov%?.<V_sz_elem>\t%P0[%c2], %1";
 }
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_mcr")]
@@ -778,7 +763,7 @@
 
   operands[0] = gen_rtx_REG (DImode, regno);
 
-  return "vmov%?.64\t%P0, %Q1, %R1";
+  return "vmov%?\t%P0, %Q1, %R1";
 }
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_mcr_2_mcrr")]
@@ -846,11 +831,11 @@
           (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
   "TARGET_NEON"
 {
-  int regno = REGNO (operands[1]) + INTVAL (operands[2]);
+  int regno = REGNO (operands[1]) + 2 * INTVAL (operands[2]);
 
   operands[1] = gen_rtx_REG (DImode, regno);
 
-  return "vmov%?.64\t%Q0, %R0, %P1";
+  return "vmov%?\t%Q0, %R0, %P1  @ v2di";
 }
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_int_1")]
@@ -867,11 +852,8 @@
 
 ;; Doubleword and quadword arithmetic.
 
-;; NOTE: vadd/vsub and some other instructions also support 64-bit integer
-;; element size, which we could potentially use for "long long" operations. We
-;; don't want to do this at present though, because moving values from the
-;; vector unit to the ARM core is currently slow and 64-bit addition (etc.) is
-;; easy to do with ARM instructions anyway.
+;; NOTE: some other instructions also support 64-bit integer
+;; element size, which we could potentially use for "long long" operations.
 
 (define_insn "*add<mode>3_neon"
   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
@@ -887,6 +869,28 @@
                     (const_string "neon_int_1")))]
 )
 
+(define_insn "adddi3_neon"
+  [(set (match_operand:DI 0 "s_register_operand" "=w,?w,&r,&r")
+        (plus:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,0")
+                 (match_operand:DI 2 "s_register_operand" "w,w,r,0")))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_NEON"
+{
+  switch (which_alternative)
+    {
+    case 0: /* fall through */
+    case 1: return "vadd.i64\t%P0, %P1, %P2";
+    case 2: return "#";
+    case 3: return "#";
+    default: gcc_unreachable ();
+    }
+}
+  [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*")
+   (set_attr "conds" "*,*,clob,clob")
+   (set_attr "length" "*,*,8,8")
+   (set_attr "alt_tune" "nota8,onlya8,*,*")]
+)
+
 (define_insn "*sub<mode>3_neon"
   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
         (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
@@ -901,6 +905,29 @@
                     (const_string "neon_int_2")))]
 )
 
+(define_insn "subdi3_neon"
+  [(set (match_operand:DI 0 "s_register_operand" "=w,?w,&r,&r,&r")
+        (minus:DI (match_operand:DI 1 "s_register_operand" "w,w,0,r,0")
+                  (match_operand:DI 2 "s_register_operand" "w,w,r,0,0")))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_NEON"
+{
+  switch (which_alternative)
+    {
+    case 0: /* fall through */
+    case 1: return "vsub.i64\t%P0, %P1, %P2";
+    case 2: /* fall through */ 
+    case 3: /* fall through */
+    case 4: return  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2";
+    default: gcc_unreachable ();
+    }
+}
+  [(set_attr "neon_type" "neon_int_2,neon_int_2,*,*,*")
+   (set_attr "conds" "*,*,clob,clob,clob")
+   (set_attr "length" "*,*,8,8,8")
+   (set_attr "alt_tune" "nota8,onlya8,*,*,*")]
+)
+
 (define_insn "*mul<mode>3_neon"
   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
         (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
@@ -922,7 +949,7 @@
                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
 )
 
-(define_insn "*mul<mode>3add<mode>_neon"
+(define_insn "mul<mode>3add<mode>_neon"
   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
         (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
                             (match_operand:VDQ 3 "s_register_operand" "w"))
@@ -944,7 +971,7 @@
                                     (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
 )
 
-(define_insn "*mul<mode>3neg<mode>add<mode>_neon"
+(define_insn "mul<mode>3neg<mode>add<mode>_neon"
   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
         (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
                    (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
@@ -984,21 +1011,26 @@
 )
 
 (define_insn "iordi3_neon"
-  [(set (match_operand:DI 0 "s_register_operand" "=w,w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0")
-		    (match_operand:DI 2 "neon_logic_op2" "w,Dl")]
-                    UNSPEC_VORR))]
+  [(set (match_operand:DI 0 "s_register_operand" "=w,?w,w,?w,&r,&r")
+        (ior:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,0,0,r")
+		(match_operand:DI 2 "neon_logic_op2" "w,w,Dl,Dl,r,r")))]
   "TARGET_NEON"
 {
   switch (which_alternative)
     {
-    case 0: return "vorr\t%P0, %P1, %P2";
-    case 1: return neon_output_logic_immediate ("vorr", &operands[2],
+    case 0: /* fall through */
+    case 1: return "vorr\t%P0, %P1, %P2";
+    case 2: /* fall through */
+    case 3: return neon_output_logic_immediate ("vorr", &operands[2],
 		     DImode, 0, VALID_NEON_QREG_MODE (DImode));
+    case 4: return "#";
+    case 5: return "#";
     default: gcc_unreachable ();
     }
 }
-  [(set_attr "neon_type" "neon_int_1")]
+  [(set_attr "neon_type" "neon_int_1,neon_int_1,neon_int_1,neon_int_1,*,*")
+   (set_attr "length" "*,*,*,*,8,8")
+   (set_attr "alt_tune" "nota8,onlya8,nota8,onlya8,*,*")]
 )
 
 ;; The concrete forms of the Neon immediate-logic instructions are vbic and
@@ -1024,21 +1056,26 @@
 )
 
 (define_insn "anddi3_neon"
-  [(set (match_operand:DI 0 "s_register_operand" "=w,w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0")
-		    (match_operand:DI 2 "neon_inv_logic_op2" "w,DL")]
-                    UNSPEC_VAND))]
+  [(set (match_operand:DI 0 "s_register_operand" "=w,?w,w,?w,&r,&r")
+        (and:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,0,0,r")
+		(match_operand:DI 2 "neon_inv_logic_op2" "w,w,DL,DL,r,r")))]
   "TARGET_NEON"
 {
   switch (which_alternative)
     {
-    case 0: return "vand\t%P0, %P1, %P2";
-    case 1: return neon_output_logic_immediate ("vand", &operands[2],
+    case 0: /* fall through */
+    case 1: return "vand\t%P0, %P1, %P2";
+    case 2: /* fall through */
+    case 3: return neon_output_logic_immediate ("vand", &operands[2],
     		     DImode, 1, VALID_NEON_QREG_MODE (DImode));
+    case 4: return "#";
+    case 5: return "#";
     default: gcc_unreachable ();
     }
 }
-  [(set_attr "neon_type" "neon_int_1")]
+  [(set_attr "neon_type" "neon_int_1,neon_int_1,neon_int_1,neon_int_1,*,*")
+   (set_attr "length" "*,*,*,*,8,8")
+   (set_attr "alt_tune" "nota8,onlya8,nota8,onlya8,*,*")]
 )
 
 (define_insn "orn<mode>3_neon"
@@ -1052,9 +1089,8 @@
 
 (define_insn "orndi3_neon"
   [(set (match_operand:DI 0 "s_register_operand" "=w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
-		    (match_operand:DI 2 "s_register_operand" "w")]
-                    UNSPEC_VORN))]
+	(ior:DI (match_operand:DI 1 "s_register_operand" "w")
+	         (not:DI (match_operand:DI 2 "s_register_operand" "w"))))]
   "TARGET_NEON"
   "vorn\t%P0, %P1, %P2"
   [(set_attr "neon_type" "neon_int_1")]
@@ -1069,14 +1105,18 @@
   [(set_attr "neon_type" "neon_int_1")]
 )
 
+;; Compare to *anddi_notdi_di.
 (define_insn "bicdi3_neon"
-  [(set (match_operand:DI 0 "s_register_operand" "=w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
-		     (match_operand:DI 2 "s_register_operand" "w")]
-                    UNSPEC_VBIC))]
+  [(set (match_operand:DI 0 "s_register_operand" "=w,=&r,&r")
+        (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,r,0"))
+		(match_operand:DI 1 "s_register_operand" "w,0,r")))]
   "TARGET_NEON"
-  "vbic\t%P0, %P1, %P2"
-  [(set_attr "neon_type" "neon_int_1")]
+  "@
+   vbic\t%P0, %P1, %P2
+   #
+   #"
+  [(set_attr "neon_type" "neon_int_1,*,*")
+   (set_attr "length" "*,8,8")]
 )
 
 (define_insn "xor<mode>3"
@@ -1089,13 +1129,18 @@
 )
 
 (define_insn "xordi3_neon"
-  [(set (match_operand:DI 0 "s_register_operand" "=w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
-		     (match_operand:DI 2 "s_register_operand" "w")]
-                    UNSPEC_VEOR))]
+  [(set (match_operand:DI 0 "s_register_operand" "=w,?w,&r,&r")
+        (xor:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,r")
+	        (match_operand:DI 2 "s_register_operand" "w,w,r,r")))]
   "TARGET_NEON"
-  "veor\t%P0, %P1, %P2"
-  [(set_attr "neon_type" "neon_int_1")]
+  "@
+   veor\t%P0, %P1, %P2
+   veor\t%P0, %P1, %P2
+   #
+   #"
+  [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*")
+   (set_attr "length" "*,*,8,8")
+   (set_attr "alt_tune" "nota8,onlya8,*,*")]
 )
 
 (define_insn "one_cmpl<mode>2"
@@ -1119,6 +1164,16 @@
                     (const_string "neon_int_3")))]
 )
 
+(define_expand "neon_vabs<mode>"
+  [(match_operand:VDQW 0 "s_register_operand" "")
+   (match_operand:VDQW 1 "s_register_operand" "")
+   (match_operand:SI 2 "immediate_operand" "")]
+  "TARGET_NEON"
+{
+  emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
+  DONE;
+})
+
 (define_insn "neg<mode>2"
   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
 	(neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
@@ -1178,7 +1233,7 @@
 ; generic vectorizer code.  It ends up creating a V2DI constructor with
 ; SImode elements.
 
-(define_insn "ashl<mode>3"
+(define_insn "vashl<mode>3"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
 	(ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
 		      (match_operand:VDQIW 2 "s_register_operand" "w")))]
@@ -1224,7 +1279,7 @@
                     (const_string "neon_shift_3")))]
 )
 
-(define_expand "ashr<mode>3"
+(define_expand "vashr<mode>3"
   [(set (match_operand:VDQIW 0 "s_register_operand" "")
 	(ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
 			(match_operand:VDQIW 2 "s_register_operand" "")))]
@@ -1238,7 +1293,7 @@
   DONE;
 })
 
-(define_expand "lshr<mode>3"
+(define_expand "vlshr<mode>3"
   [(set (match_operand:VDQIW 0 "s_register_operand" "")
 	(lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
 			(match_operand:VDQIW 2 "s_register_operand" "")))]
@@ -1755,21 +1810,17 @@
 
 ; good for plain vadd, vaddq.
 
-(define_insn "neon_vadd<mode>"
-  [(set (match_operand:VDQX 0 "s_register_operand" "=w")
-        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
-		      (match_operand:VDQX 2 "s_register_operand" "w")
-                      (match_operand:SI 3 "immediate_operand" "i")]
-                     UNSPEC_VADD))]
+(define_expand "neon_vadd<mode>"
+  [(match_operand:VDQX 0 "s_register_operand" "=w")
+   (match_operand:VDQX 1 "s_register_operand" "w")
+   (match_operand:VDQX 2 "s_register_operand" "w")
+   (match_operand:SI 3 "immediate_operand" "i")]
   "TARGET_NEON"
-  "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
-  [(set (attr "neon_type")
-      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
-                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
-                    (const_string "neon_int_1")))]
-)
+{
+  emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[2]));
+  DONE;
+})
+
 
 ; operand 3 represents in bits:
 ;  bit 0: signed (vs unsigned).
@@ -1832,6 +1883,8 @@
   [(set_attr "neon_type" "neon_int_4")]
 )
 
+;; We cannot replace this unspec with mul<mode>3 because of the odd 
+;; polynomial multiplication case that can specified by operand 3.
 (define_insn "neon_vmul<mode>"
   [(set (match_operand:VDQW 0 "s_register_operand" "=w")
         (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
@@ -1855,29 +1908,18 @@
                                     (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
 )
 
-(define_insn "neon_vmla<mode>"
-  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
-        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
-		      (match_operand:VDQW 2 "s_register_operand" "w")
-		      (match_operand:VDQW 3 "s_register_operand" "w")
-                     (match_operand:SI 4 "immediate_operand" "i")]
-                    UNSPEC_VMLA))]
+(define_expand "neon_vmla<mode>"
+  [(match_operand:VDQW 0 "s_register_operand" "=w")
+   (match_operand:VDQW 1 "s_register_operand" "0")
+   (match_operand:VDQW 2 "s_register_operand" "w")
+   (match_operand:VDQW 3 "s_register_operand" "w")
+   (match_operand:SI 4 "immediate_operand" "i")]
   "TARGET_NEON"
-  "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
-  [(set (attr "neon_type")
-      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                                  (const_string "neon_fp_vmla_ddd")
-                                  (const_string "neon_fp_vmla_qqq"))
-                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                                  (if_then_else
-                                    (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
-                                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
-                                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
-                                  (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
-                                    (const_string "neon_mla_qqq_8_16")
-                                    (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
-)
+{
+  emit_insn (gen_mul<mode>3add<mode>_neon (operands[0], operands[1],
+				           operands[2], operands[3]));
+  DONE;
+})
 
 (define_insn "neon_vmlal<mode>"
   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
@@ -1894,30 +1936,18 @@
                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
 )
 
-(define_insn "neon_vmls<mode>"
-  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
-        (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
-		      (match_operand:VDQW 2 "s_register_operand" "w")
-		      (match_operand:VDQW 3 "s_register_operand" "w")
-                     (match_operand:SI 4 "immediate_operand" "i")]
-                    UNSPEC_VMLS))]
+(define_expand "neon_vmls<mode>"
+  [(match_operand:VDQW 0 "s_register_operand" "=w")
+   (match_operand:VDQW 1 "s_register_operand" "0")
+   (match_operand:VDQW 2 "s_register_operand" "w")
+   (match_operand:VDQW 3 "s_register_operand" "w")
+   (match_operand:SI 4 "immediate_operand" "i")]
   "TARGET_NEON"
-  "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
-  [(set (attr "neon_type")
-      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                                  (const_string "neon_fp_vmla_ddd")
-                                  (const_string "neon_fp_vmla_qqq"))
-                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                                  (if_then_else
-                                    (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
-                                    (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
-                                    (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
-                                  (if_then_else
-                                    (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
-                                    (const_string "neon_mla_qqq_8_16")
-                                    (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
-)
+{
+  emit_insn (gen_mul<mode>3neg<mode>add<mode>_neon (operands[0], operands[1],
+						    operands[2], operands[3]));
+  DONE;
+})
 
 (define_insn "neon_vmlsl<mode>"
   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
@@ -2010,21 +2040,16 @@
                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
 )
 
-(define_insn "neon_vsub<mode>"
-  [(set (match_operand:VDQX 0 "s_register_operand" "=w")
-        (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
-		      (match_operand:VDQX 2 "s_register_operand" "w")
-                      (match_operand:SI 3 "immediate_operand" "i")]
-                     UNSPEC_VSUB))]
+(define_expand "neon_vsub<mode>"
+  [(match_operand:VDQX 0 "s_register_operand" "=w")
+   (match_operand:VDQX 1 "s_register_operand" "w")
+   (match_operand:VDQX 2 "s_register_operand" "w")
+   (match_operand:SI 3 "immediate_operand" "i")]
   "TARGET_NEON"
-  "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
-  [(set (attr "neon_type")
-      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                    (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                                  (const_string "neon_fp_vadd_ddd_vabs_dd")
-                                  (const_string "neon_fp_vadd_qqq_vabs_qq"))
-                    (const_string "neon_int_2")))]
-)
+{
+  emit_insn (gen_sub<mode>3 (operands[0], operands[1], operands[2]));
+  DONE;
+})
 
 (define_insn "neon_vsubl<mode>"
   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
@@ -2197,11 +2222,11 @@
 
 (define_insn "neon_vaba<mode>"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
-        (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "0")
-		       (match_operand:VDQIW 2 "s_register_operand" "w")
-		       (match_operand:VDQIW 3 "s_register_operand" "w")
-                       (match_operand:SI 4 "immediate_operand" "i")]
-		      UNSPEC_VABA))]
+        (plus:VDQIW (match_operand:VDQIW 1 "s_register_operand" "0")
+                    (unspec:VDQIW [(match_operand:VDQIW 2 "s_register_operand" "w")
+		                   (match_operand:VDQIW 3 "s_register_operand" "w")
+                                   (match_operand:SI 4 "immediate_operand" "i")]
+		                  UNSPEC_VABD)))]
   "TARGET_NEON"
   "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
   [(set (attr "neon_type")
@@ -2211,11 +2236,11 @@
 
 (define_insn "neon_vabal<mode>"
   [(set (match_operand:<V_widen> 0 "s_register_operand" "=w")
-        (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0")
-		           (match_operand:VW 2 "s_register_operand" "w")
-		           (match_operand:VW 3 "s_register_operand" "w")
-                           (match_operand:SI 4 "immediate_operand" "i")]
-                          UNSPEC_VABAL))]
+        (plus:<V_widen> (match_operand:<V_widen> 1 "s_register_operand" "0")
+                        (unspec:<V_widen> [(match_operand:VW 2 "s_register_operand" "w")
+                                           (match_operand:VW 3 "s_register_operand" "w")
+                                           (match_operand:SI 4 "immediate_operand" "i")]
+                          UNSPEC_VABDL)))]
   "TARGET_NEON"
   "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
   [(set_attr "neon_type" "neon_vaba")]
@@ -2346,23 +2371,6 @@
                     (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
 )
 
-(define_insn "neon_vabs<mode>"
-  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
-	(unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w")
-		      (match_operand:SI 2 "immediate_operand" "i")]
-                     UNSPEC_VABS))]
-  "TARGET_NEON"
-  "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
-  [(set (attr "neon_type")
-     (if_then_else (ior (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                        (ne (symbol_ref "<Is_float_mode>") (const_int 0)))
-                   (if_then_else
-                      (ne (symbol_ref "<Is_d_reg>") (const_int 0))
-                      (const_string "neon_fp_vadd_ddd_vabs_dd")
-                      (const_string "neon_fp_vadd_qqq_vabs_qq"))
-                   (const_string "neon_vqneg_vqabs")))]
-)
-
 (define_insn "neon_vqabs<mode>"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
 	(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
@@ -2403,26 +2411,42 @@
   [(set_attr "neon_type" "neon_int_1")]
 )
 
-(define_insn "neon_vclz<mode>"
+(define_insn "clz<mode>2"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
-	(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
-		       (match_operand:SI 2 "immediate_operand" "i")]
-		      UNSPEC_VCLZ))]
+        (clz:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")))]
   "TARGET_NEON"
   "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
   [(set_attr "neon_type" "neon_int_1")]
 )
 
-(define_insn "neon_vcnt<mode>"
+(define_expand "neon_vclz<mode>"
+  [(match_operand:VDQIW 0 "s_register_operand" "")
+   (match_operand:VDQIW 1 "s_register_operand" "")
+   (match_operand:SI 2 "immediate_operand" "")]
+  "TARGET_NEON"
+{
+  emit_insn (gen_clz<mode>2 (operands[0], operands[1]));
+  DONE;
+})
+
+(define_insn "popcount<mode>2"
   [(set (match_operand:VE 0 "s_register_operand" "=w")
-	(unspec:VE [(match_operand:VE 1 "s_register_operand" "w")
-                    (match_operand:SI 2 "immediate_operand" "i")]
-                   UNSPEC_VCNT))]
+        (popcount:VE (match_operand:VE 1 "s_register_operand" "w")))]
   "TARGET_NEON"
   "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
   [(set_attr "neon_type" "neon_int_1")]
 )
 
+(define_expand "neon_vcnt<mode>"
+  [(match_operand:VE 0 "s_register_operand" "=w")
+   (match_operand:VE 1 "s_register_operand" "w")
+   (match_operand:SI 2 "immediate_operand" "i")]
+  "TARGET_NEON"
+{
+  emit_insn (gen_popcount<mode>2 (operands[0], operands[1]));
+  DONE;
+})
+
 (define_insn "neon_vrecpe<mode>"
   [(set (match_operand:V32 0 "s_register_operand" "=w")
 	(unspec:V32 [(match_operand:V32 1 "s_register_operand" "w")
@@ -2599,126 +2623,65 @@
 ; Operand 3 (info word) is ignored because it does nothing useful with 64-bit
 ; elements.
 
-(define_insn "neon_vget_lanedi"
-  [(set (match_operand:DI 0 "s_register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
-                   (match_operand:SI 2 "immediate_operand" "i")
-                   (match_operand:SI 3 "immediate_operand" "i")]
-                  UNSPEC_VGET_LANE))]
+(define_expand "neon_vget_lanedi"
+  [(match_operand:DI 0 "s_register_operand" "=r")
+   (match_operand:DI 1 "s_register_operand" "w")
+   (match_operand:SI 2 "immediate_operand" "i")
+   (match_operand:SI 3 "immediate_operand" "i")]
   "TARGET_NEON"
 {
   neon_lane_bounds (operands[2], 0, 1);
-  return "vmov%?\t%Q0, %R0, %P1  @ di";
-}
-  [(set_attr "predicable" "yes")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
 
-(define_insn "neon_vget_lanev2di"
-  [(set (match_operand:DI 0 "s_register_operand" "=r")
-       (unspec:DI [(match_operand:V2DI 1 "s_register_operand" "w")
-                   (match_operand:SI 2 "immediate_operand" "i")
-                   (match_operand:SI 3 "immediate_operand" "i")]
-                  UNSPEC_VGET_LANE))]
+(define_expand "neon_vget_lanev2di"
+  [(match_operand:DI 0 "s_register_operand" "=r")
+   (match_operand:V2DI 1 "s_register_operand" "w")
+   (match_operand:SI 2 "immediate_operand" "i")
+   (match_operand:SI 3 "immediate_operand" "i")]
   "TARGET_NEON"
 {
-  rtx ops[2];
-  unsigned int regno = REGNO (operands[1]);
-  unsigned int elt = INTVAL (operands[2]);
-
   neon_lane_bounds (operands[2], 0, 2);
+  emit_insn (gen_vec_extractv2di (operands[0], operands[1], operands[2]));
+  DONE;
+})
 
-  ops[0] = operands[0];
-  ops[1] = gen_rtx_REG (DImode, regno + 2 * elt);
-  output_asm_insn ("vmov%?\t%Q0, %R0, %P1  @ v2di", ops);
-
-  return "";
-}
-  [(set_attr "predicable" "yes")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
-
-(define_insn "neon_vset_lane<mode>"
-  [(set (match_operand:VD 0 "s_register_operand" "=w")
-	(unspec:VD [(match_operand:<V_elem> 1 "s_register_operand" "r")
-		    (match_operand:VD 2 "s_register_operand" "0")
-                    (match_operand:SI 3 "immediate_operand" "i")]
-                   UNSPEC_VSET_LANE))]
-  "TARGET_NEON"
-{
-  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
-  return "vmov%?.<V_sz_elem>\t%P0[%c3], %1";
-}
-  [(set_attr "predicable" "yes")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
-
-; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
-
-(define_insn "neon_vset_lanedi"
-  [(set (match_operand:DI 0 "s_register_operand" "=w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "r")
-		    (match_operand:DI 2 "s_register_operand" "0")
-                    (match_operand:SI 3 "immediate_operand" "i")]
-                   UNSPEC_VSET_LANE))]
-  "TARGET_NEON"
-{
-  neon_lane_bounds (operands[3], 0, 1);
-  return "vmov%?\t%P0, %Q1, %R1  @ di";
-}
-  [(set_attr "predicable" "yes")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
-
-(define_insn "neon_vset_lane<mode>"
-  [(set (match_operand:VQ 0 "s_register_operand" "=w")
-	(unspec:VQ [(match_operand:<V_elem> 1 "s_register_operand" "r")
-		    (match_operand:VQ 2 "s_register_operand" "0")
-                    (match_operand:SI 3 "immediate_operand" "i")]
-                   UNSPEC_VSET_LANE))]
+(define_expand "neon_vset_lane<mode>"
+  [(match_operand:VDQ 0 "s_register_operand" "=w")
+   (match_operand:<V_elem> 1 "s_register_operand" "r")
+   (match_operand:VDQ 2 "s_register_operand" "0")
+   (match_operand:SI 3 "immediate_operand" "i")]
   "TARGET_NEON"
 {
-  rtx ops[4];
-  unsigned int regno = REGNO (operands[0]);
-  unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
   unsigned int elt = INTVAL (operands[3]);
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
 
-  neon_lane_bounds (operands[3], 0, halfelts * 2);
+  if (BYTES_BIG_ENDIAN)
+    {
+      unsigned int reg_nelts
+	= 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
+      elt ^= reg_nelts - 1;
+    }
 
-  ops[0] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
-  ops[1] = operands[1];
-  ops[2] = GEN_INT (elt % halfelts);
-  output_asm_insn ("vmov%?.<V_sz_elem>\t%P0[%c2], %1", ops);
+  emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1],
+                                         GEN_INT (1 << elt), operands[2]));
+  DONE;
+})
 
-  return "";
-}
-  [(set_attr "predicable" "yes")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
+; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
 
-(define_insn "neon_vset_lanev2di"
-  [(set (match_operand:V2DI 0 "s_register_operand" "=w")
-	(unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")
-		      (match_operand:V2DI 2 "s_register_operand" "0")
-                      (match_operand:SI 3 "immediate_operand" "i")]
-                   UNSPEC_VSET_LANE))]
+(define_expand "neon_vset_lanedi"
+  [(match_operand:DI 0 "s_register_operand" "=w")
+   (match_operand:DI 1 "s_register_operand" "r")
+   (match_operand:DI 2 "s_register_operand" "0")
+   (match_operand:SI 3 "immediate_operand" "i")]
   "TARGET_NEON"
 {
-  rtx ops[2];
-  unsigned int regno = REGNO (operands[0]);
-  unsigned int elt = INTVAL (operands[3]);
-
-  neon_lane_bounds (operands[3], 0, 2);
-
-  ops[0] = gen_rtx_REG (DImode, regno + 2 * elt);
-  ops[1] = operands[1];
-  output_asm_insn ("vmov%?\t%P0, %Q1, %R1  @ v2di", ops);
-
-  return "";
-}
-  [(set_attr "predicable" "yes")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
+  neon_lane_bounds (operands[3], 0, 1);
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
 
 (define_expand "neon_vcreate<mode>"
   [(match_operand:VDX 0 "s_register_operand" "")
@@ -2731,9 +2694,8 @@
 })
 
 (define_insn "neon_vdup_n<mode>"
-  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
-	(unspec:VDQW [(match_operand:<V_elem> 1 "s_register_operand" "r")]
-                    UNSPEC_VDUP_N))]
+  [(set (match_operand:VX 0 "s_register_operand" "=w")
+        (vec_duplicate:VX (match_operand:<V_elem> 1 "s_register_operand" "r")))]
   "TARGET_NEON"
   "vdup%?.<V_sz_elem>\t%<V_reg>0, %1"
   ;; Assume this schedules like vmov.
@@ -2741,61 +2703,88 @@
    (set_attr "neon_type" "neon_bp_simple")]
 )
 
-(define_insn "neon_vdup_ndi"
-  [(set (match_operand:DI 0 "s_register_operand" "=w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
-                   UNSPEC_VDUP_N))]
+(define_insn "neon_vdup_n<mode>"
+  [(set (match_operand:V32 0 "s_register_operand" "=w,w")
+        (vec_duplicate:V32 (match_operand:<V_elem> 1 "s_register_operand" "r,t")))]
   "TARGET_NEON"
-  "vmov%?\t%P0, %Q1, %R1"
+  "@
+  vdup%?.<V_sz_elem>\t%<V_reg>0, %1
+  vdup%?.<V_sz_elem>\t%<V_reg>0, %y1"
+  ;; Assume this schedules like vmov.
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_bp_simple")]
 )
 
+(define_expand "neon_vdup_ndi"
+  [(match_operand:DI 0 "s_register_operand" "=w")
+   (match_operand:DI 1 "s_register_operand" "r")]
+  "TARGET_NEON"
+{
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+}
+)
+
 (define_insn "neon_vdup_nv2di"
-  [(set (match_operand:V2DI 0 "s_register_operand" "=w")
-	(unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")]
-                     UNSPEC_VDUP_N))]
+  [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
+        (vec_duplicate:V2DI (match_operand:DI 1 "s_register_operand" "r,w")))]
   "TARGET_NEON"
-  "vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1"
+  "@
+  vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1
+  vmov%?\t%e0, %P1\;vmov%?\t%f0, %P1"
   [(set_attr "predicable" "yes")
    (set_attr "length" "8")
    (set_attr "neon_type" "neon_bp_simple")]
 )
 
-(define_insn "neon_vdup_lane<mode>"
-  [(set (match_operand:VD 0 "s_register_operand" "=w")
-	(unspec:VD [(match_operand:VD 1 "s_register_operand" "w")
-		    (match_operand:SI 2 "immediate_operand" "i")]
-                   UNSPEC_VDUP_LANE))]
+(define_insn "neon_vdup_lane<mode>_internal"
+  [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+  	(vec_duplicate:VDQW 
+          (vec_select:<V_elem>
+            (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
+            (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
   "TARGET_NEON"
 {
-  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
-  return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
+  if (BYTES_BIG_ENDIAN)
+    {
+      int elt = INTVAL (operands[2]);
+      elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt;
+      operands[2] = GEN_INT (elt);
+    }
+  if (<Is_d_reg>)
+    return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
+  else
+    return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
 }
   ;; Assume this schedules like vmov.
   [(set_attr "neon_type" "neon_bp_simple")]
 )
 
-(define_insn "neon_vdup_lane<mode>"
-  [(set (match_operand:VQ 0 "s_register_operand" "=w")
-	(unspec:VQ [(match_operand:<V_HALF> 1 "s_register_operand" "w")
-		    (match_operand:SI 2 "immediate_operand" "i")]
-                   UNSPEC_VDUP_LANE))]
+(define_expand "neon_vdup_lane<mode>"
+  [(match_operand:VDQW 0 "s_register_operand" "=w")
+   (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
+   (match_operand:SI 2 "immediate_operand" "i")]
   "TARGET_NEON"
 {
-  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_HALF>mode));
-  return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
-}
-  ;; Assume this schedules like vmov.
-  [(set_attr "neon_type" "neon_bp_simple")]
-)
+  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_double_vector_mode>mode));
+  if (BYTES_BIG_ENDIAN)
+    {
+      unsigned int elt = INTVAL (operands[2]);
+      unsigned int reg_nelts
+	= 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<V_double_vector_mode>mode));
+      elt ^= reg_nelts - 1;
+      operands[2] = GEN_INT (elt);
+    }
+    emit_insn (gen_neon_vdup_lane<mode>_internal (operands[0], operands[1],
+                                                  operands[2]));
+    DONE;
+})
 
 ; Scalar index is ignored, since only zero is valid here.
 (define_expand "neon_vdup_lanedi"
-  [(set (match_operand:DI 0 "s_register_operand" "=w")
-	(unspec:DI [(match_operand:DI 1 "s_register_operand" "w")
-		    (match_operand:SI 2 "immediate_operand" "i")]
-                   UNSPEC_VDUP_LANE))]
+  [(match_operand:DI 0 "s_register_operand" "=w")
+   (match_operand:DI 1 "s_register_operand" "w")
+   (match_operand:SI 2 "immediate_operand" "i")]
   "TARGET_NEON"
 {
   neon_lane_bounds (operands[2], 0, 1);
@@ -2803,20 +2792,17 @@
   DONE;
 })
 
-; Likewise.
-(define_insn "neon_vdup_lanev2di"
-  [(set (match_operand:V2DI 0 "s_register_operand" "=w")
-	(unspec:V2DI [(match_operand:DI 1 "s_register_operand" "w")
-		      (match_operand:SI 2 "immediate_operand" "i")]
-                     UNSPEC_VDUP_LANE))]
+; Likewise for v2di, as the DImode second operand has only a single element.
+(define_expand "neon_vdup_lanev2di"
+  [(match_operand:V2DI 0 "s_register_operand" "=w")
+   (match_operand:DI 1 "s_register_operand" "w")
+   (match_operand:SI 2 "immediate_operand" "i")]
   "TARGET_NEON"
 {
   neon_lane_bounds (operands[2], 0, 1);
-  return "vmov\t%e0, %P1\;vmov\t%f0, %P1";
-}
-  [(set_attr "length" "8")
-   (set_attr "neon_type" "neon_bp_simple")]
-)
+  emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
+  DONE;
+})
 
 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
 ;; dest vector.
@@ -2827,9 +2813,8 @@
 
 (define_insn "neon_vcombine<mode>"
   [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w")
-	(unspec:<V_DOUBLE> [(match_operand:VDX 1 "s_register_operand" "w")
-			    (match_operand:VDX 2 "s_register_operand" "w")]
-                           UNSPEC_VCOMBINE))]
+        (vec_concat:<V_DOUBLE> (match_operand:VDX 1 "s_register_operand" "w")
+			       (match_operand:VDX 2 "s_register_operand" "w")))]
   "TARGET_NEON"
 {
   int dest = REGNO (operands[0]);
@@ -2869,10 +2854,31 @@
    (set_attr "neon_type" "neon_bp_simple")]
 )
 
-(define_insn "neon_vget_high<mode>"
-  [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w")
-	(unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")]
-			 UNSPEC_VGET_HIGH))]
+(define_insn "neon_vget_highv16qi"
+  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
+	(vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
+                         (parallel [(const_int 8) (const_int 9)
+			            (const_int 10) (const_int 11)
+				    (const_int 12) (const_int 13)
+				    (const_int 14) (const_int 15)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src + 2)
+    return "vmov\t%P0, %f1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_highv8hi"
+  [(set (match_operand:V4HI 0 "s_register_operand" "=w")
+	(vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
+	                 (parallel [(const_int 4) (const_int 5)
+			            (const_int 6) (const_int 7)])))]
   "TARGET_NEON"
 {
   int dest = REGNO (operands[0]);
@@ -2886,10 +2892,133 @@
   [(set_attr "neon_type" "neon_bp_simple")]
 )
 
-(define_insn "neon_vget_low<mode>"
-  [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w")
-	(unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")]
-			 UNSPEC_VGET_LOW))]
+(define_insn "neon_vget_highv4si"
+  [(set (match_operand:V2SI 0 "s_register_operand" "=w")
+	(vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
+	                 (parallel [(const_int 2) (const_int 3)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src + 2)
+    return "vmov\t%P0, %f1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_highv4sf"
+  [(set (match_operand:V2SF 0 "s_register_operand" "=w")
+	(vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
+	                 (parallel [(const_int 2) (const_int 3)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src + 2)
+    return "vmov\t%P0, %f1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_highv2di"
+  [(set (match_operand:DI 0 "s_register_operand" "=w")
+	(vec_select:DI (match_operand:V2DI 1 "s_register_operand" "w")
+	               (parallel [(const_int 1)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src + 2)
+    return "vmov\t%P0, %f1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_lowv16qi"
+  [(set (match_operand:V8QI 0 "s_register_operand" "=w")
+	(vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w")
+                         (parallel [(const_int 0) (const_int 1)
+			            (const_int 2) (const_int 3)
+				    (const_int 4) (const_int 5)
+				    (const_int 6) (const_int 7)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src)
+    return "vmov\t%P0, %e1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_lowv8hi"
+  [(set (match_operand:V4HI 0 "s_register_operand" "=w")
+	(vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w")
+	                 (parallel [(const_int 0) (const_int 1)
+			            (const_int 2) (const_int 3)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src)
+    return "vmov\t%P0, %e1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_lowv4si"
+  [(set (match_operand:V2SI 0 "s_register_operand" "=w")
+	(vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w")
+	                 (parallel [(const_int 0) (const_int 1)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src)
+    return "vmov\t%P0, %e1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_lowv4sf"
+  [(set (match_operand:V2SF 0 "s_register_operand" "=w")
+	(vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w")
+	                 (parallel [(const_int 0) (const_int 1)])))]
+  "TARGET_NEON"
+{
+  int dest = REGNO (operands[0]);
+  int src = REGNO (operands[1]);
+
+  if (dest != src)
+    return "vmov\t%P0, %e1";
+  else
+    return "";
+}
+  [(set_attr "neon_type" "neon_bp_simple")]
+)
+
+(define_insn "neon_vget_lowv2di"
+  [(set (match_operand:DI 0 "s_register_operand" "=w")
+	(vec_select:DI (match_operand:V2DI 1 "s_register_operand" "w")
+	               (parallel [(const_int 0)])))]
   "TARGET_NEON"
 {
   int dest = REGNO (operands[0]);
diff -Naur a/src/gcc/config/arm/neon.ml b/src/gcc/config/arm/neon.ml
--- a/src/gcc/config/arm/neon.ml	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/neon.ml	2010-03-30 10:39:38.000000000 +0300
@@ -68,6 +68,7 @@
 	       | Element_of_dreg	(* Used for "lane" variants.  *)
 	       | Element_of_qreg	(* Likewise.  *)
 	       | All_elements_of_dreg	(* Used for "dup" variants.  *)
+	       | Alternatives of shape_elt list (* Used for multiple valid operands *)
 
 type shape_form = All of int * shape_elt
                 | Long
@@ -965,7 +966,8 @@
       Use_operands [| Corereg; Dreg; Immed |],
       "vget_lane", get_lane, pf_su_8_32;
     Vget_lane,
-      [InfoWord;
+      [No_op;
+       InfoWord;
        Disassembles_as [Use_operands [| Corereg; Corereg; Dreg |]];
        Instruction_name ["vmov"]; Const_valuator (fun _ -> 0)],
       Use_operands [| Corereg; Dreg; Immed |],
@@ -987,7 +989,8 @@
                 Instruction_name ["vmov"]],
       Use_operands [| Dreg; Corereg; Dreg; Immed |], "vset_lane",
       set_lane, pf_su_8_32;
-    Vset_lane, [Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]];
+    Vset_lane, [No_op;
+                Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]];
                 Instruction_name ["vmov"]; Const_valuator (fun _ -> 0)],
       Use_operands [| Dreg; Corereg; Dreg; Immed |], "vset_lane",
       set_lane_notype, [S64; U64];
@@ -1008,19 +1011,27 @@
       pf_su_8_64;
 
     (* Set all lanes to the same value.  *)
-    Vdup_n, [],
+    Vdup_n,
+      [Disassembles_as [Use_operands [| Dreg;
+                                        Alternatives [ Corereg;
+                                                       Element_of_dreg ] |]]],
       Use_operands [| Dreg; Corereg |], "vdup_n", bits_1,
       pf_su_8_32;
     Vdup_n,
-      [Instruction_name ["vmov"];
+      [No_op;
+       Instruction_name ["vmov"];
        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]]],
       Use_operands [| Dreg; Corereg |], "vdup_n", notype_1,
       [S64; U64];
-    Vdup_n, [],
+    Vdup_n,
+      [Disassembles_as [Use_operands [| Qreg;
+                                        Alternatives [ Corereg;
+                                                       Element_of_dreg ] |]]],
       Use_operands [| Qreg; Corereg |], "vdupQ_n", bits_1,
       pf_su_8_32;
     Vdup_n,
-      [Instruction_name ["vmov"];
+      [No_op;
+       Instruction_name ["vmov"];
        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |];
                         Use_operands [| Dreg; Corereg; Corereg |]]],
       Use_operands [| Qreg; Corereg |], "vdupQ_n", notype_1,
@@ -1028,21 +1039,29 @@
 
     (* These are just aliases for the above.  *)
     Vmov_n,
-      [Builtin_name "vdup_n"],
+      [Builtin_name "vdup_n";
+       Disassembles_as [Use_operands [| Dreg;
+                                        Alternatives [ Corereg;
+                                                       Element_of_dreg ] |]]],
       Use_operands [| Dreg; Corereg |],
       "vmov_n", bits_1, pf_su_8_32;
     Vmov_n,
-      [Builtin_name "vdup_n";
+      [No_op;
+       Builtin_name "vdup_n";
        Instruction_name ["vmov"];
        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |]]],
       Use_operands [| Dreg; Corereg |],
       "vmov_n", notype_1, [S64; U64];
     Vmov_n,
-      [Builtin_name "vdupQ_n"],
+      [Builtin_name "vdupQ_n";
+       Disassembles_as [Use_operands [| Qreg;
+                                        Alternatives [ Corereg;
+                                                       Element_of_dreg ] |]]],
       Use_operands [| Qreg; Corereg |],
       "vmovQ_n", bits_1, pf_su_8_32;
     Vmov_n,
-      [Builtin_name "vdupQ_n";
+      [No_op;
+       Builtin_name "vdupQ_n";
        Instruction_name ["vmov"];
        Disassembles_as [Use_operands [| Dreg; Corereg; Corereg |];
                         Use_operands [| Dreg; Corereg; Corereg |]]],
diff -Naur a/src/gcc/config/arm/neon-testgen.ml b/src/gcc/config/arm/neon-testgen.ml
--- a/src/gcc/config/arm/neon-testgen.ml	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/neon-testgen.ml	2010-03-30 10:39:38.000000000 +0300
@@ -175,6 +175,7 @@
     | Element_of_dreg -> (analyze_shape_elt Dreg) ^ "\\\\\\[\\[0-9\\]+\\\\\\]"
     | Element_of_qreg -> (analyze_shape_elt Qreg) ^ "\\\\\\[\\[0-9\\]+\\\\\\]"
     | All_elements_of_dreg -> (analyze_shape_elt Dreg) ^ "\\\\\\[\\\\\\]"
+    | Alternatives (elts) -> "(" ^ (String.concat "|" (List.map analyze_shape_elt elts)) ^ ")"
   in
     match shape with
       All (n, elt) -> commas analyze_shape_elt (n_things n elt) ""
diff -Naur a/src/gcc/config/arm/nucleus.h b/src/gcc/config/arm/nucleus.h
--- a/src/gcc/config/arm/nucleus.h	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/nucleus.h	2010-04-02 10:28:17.000000000 +0300
@@ -0,0 +1,41 @@
+/* Configuration file for ARM nucleus targets.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+   Contributed by Nathan Sidwell (nathan@codesourcery.com)
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#if NUCLEUS_SHARED_EXEC
+/* Executables are really shared objects, so default to building a .so
+ */
+#undef LINK_SPEC
+#define LINK_SPEC "%{!static:%{!shared:-shared -z defs}} " BPABI_LINK_SPEC
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crti%O%s %{!static:crtbeginS%O%s;:crtbegin%O%s}"
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{!static:crtendS%O%s;:crtend%O%s} crtn%O%s"
+#endif
+
+/* wide chars are 16 bit */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short int"
+#define WCHAR_TYPE_SIZE 16
+
+/* Use --as-needed -lgcc_s for eh support.  */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
diff -Naur a/src/gcc/config/arm/pe-cxx.c b/src/gcc/config/arm/pe-cxx.c
--- a/src/gcc/config/arm/pe-cxx.c	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/pe-cxx.c	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,167 @@
+/* Target support for C++ classes on Windows.
+   Contributed by Danny Smith (dannysmith@users.sourceforge.net)
+   Copyright (C) 2005
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "cp/cp-tree.h" /* this is why we're a separate module */
+#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "hashtab.h"
+
+bool
+arm_pe_type_dllimport_p (tree decl)
+{
+   gcc_assert (TREE_CODE (decl) == VAR_DECL
+               || TREE_CODE (decl) == FUNCTION_DECL);
+
+   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
+     return false;
+
+   /* We ignore the dllimport attribute for inline member functions.
+      This differs from MSVC behavior which treats it like GNUC
+      'extern inline' extension.  Also ignore for template
+      instantiations with linkonce semantics and artificial methods.  */
+    if (TREE_CODE (decl) ==  FUNCTION_DECL
+        && (DECL_DECLARED_INLINE_P (decl)
+	    || DECL_TEMPLATE_INSTANTIATION (decl)
+	    || DECL_ARTIFICIAL (decl)))
+      return false;
+
+   /* Since we can't treat a pointer to a dllimport'd symbol as a
+       constant address, we turn off the attribute on C++ virtual
+       methods to allow creation of vtables using thunks.  */
+    else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
+	     && DECL_VIRTUAL_P (decl))
+      {
+	/* Even though we ignore the attribute from the start, warn if we later see
+	   an out-of class definition, as we do for other member functions in
+	   tree.c:merge_dllimport_decl_attributes.  If this is the key method, the
+	   definition may affect the import-export status of vtables, depending
+           on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c.   */
+	if (DECL_INITIAL (decl))
+	  {
+	    warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
+		    "previous dllimport ignored", decl);
+#ifdef PE_DLL_DEBUG
+	    if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl)))            
+	      warning (OPT_Wattributes, "key method %q+D of dllimport'd class defined"
+		       decl);
+#endif
+	  }
+	return false;
+      }
+
+      /* Don't mark defined functions as dllimport.  This code will only be
+         reached if we see a non-inline function defined out-of-class.  */
+    else if (TREE_CODE (decl) ==  FUNCTION_DECL
+	     && (DECL_INITIAL (decl)))
+      return false;
+
+    /*  Don't allow definitions of static data members in dllimport class,
+        If vtable data is marked as DECL_EXTERNAL, import it; otherwise just
+        ignore the class attribute.  */
+    else if (TREE_CODE (decl) == VAR_DECL
+	     && TREE_STATIC (decl) && TREE_PUBLIC (decl)
+	     && !DECL_EXTERNAL (decl))
+      {
+	if (!DECL_VIRTUAL_P (decl))
+	     error ("definition of static data member %q+D of "
+		    "dllimport'd class", decl);
+	return false;
+      }
+
+    return true;
+}
+
+
+bool
+arm_pe_type_dllexport_p (tree decl)
+{
+   gcc_assert (TREE_CODE (decl) == VAR_DECL 
+               || TREE_CODE (decl) == FUNCTION_DECL);
+   /* Avoid exporting compiler-generated default dtors and copy ctors.
+      The only artificial methods that need to be exported are virtual
+      and non-virtual thunks.  */
+   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
+       && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
+     return false;
+   return true;
+}
+
+static inline void maybe_add_dllimport (tree decl)
+/* void maybe_add_dllimport (tree decl) */
+{
+  if (arm_pe_type_dllimport_p (decl))
+    DECL_DLLIMPORT_P (decl) = 1;   
+}
+
+void
+arm_pe_adjust_class_at_definition (tree t)
+{
+  tree member;
+
+  gcc_assert (CLASS_TYPE_P (t));
+
+ /* We only look at dllimport.  The only thing that dllexport does is
+    add stuff to a '.drectiv' section at end-of-file, so no need to do
+    anything for dllexport'd classes until we generate RTL. */  
+  if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE)
+    return;
+
+  /* We don't actually add the attribute to the decl, just set the flag
+     that signals that the address of this symbol is not a compile-time
+     constant.   Any subsequent out-of-class declaration of members wil
+     cause the DECL_DLLIMPORT_P flag to be unset.
+     (See  tree.c: merge_dllimport_decl_attributes).
+     That is just right since out-of class declarations can only be a
+     definition.  We recheck the class members  at RTL generation to
+     emit warnings if this has happened.  Definition of static data member
+     of dllimport'd class always causes an error (as per MS compiler).
+     */
+
+  /* Check static VAR_DECL's.  */
+  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
+    if (TREE_CODE (member) == VAR_DECL)     
+      maybe_add_dllimport (member);
+    
+  /* Check FUNCTION_DECL's.  */
+  for (member = TYPE_METHODS (t); member;  member = TREE_CHAIN (member))
+    if (TREE_CODE (member) == FUNCTION_DECL)      
+      maybe_add_dllimport (member);
+ 
+  /* Check vtables  */
+  for (member = CLASSTYPE_VTABLES (t); member;  member = TREE_CHAIN (member))
+    if (TREE_CODE (member) == VAR_DECL) 
+      maybe_add_dllimport (member);
+
+/* We leave typeinfo tables alone.  We can't mark TI objects as
+     dllimport, since the address of a secondary VTT may be needed
+     for static initialization of a primary VTT.  VTT's  of
+     dllimport'd classes should always be link-once COMDAT.  */ 
+}
diff -Naur a/src/gcc/config/arm/pe.opt b/src/gcc/config/arm/pe.opt
--- a/src/gcc/config/arm/pe.opt	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/pe.opt	2010-03-30 10:39:38.000000000 +0300
@@ -21,3 +21,7 @@
 mnop-fun-dllimport
 Target Report Mask(NOP_FUN_DLLIMPORT)
 Ignore dllimport attribute for functions
+
+mms-bitfields
+Target Report Mask(MS_BITFIELD_LAYOUT)
+Use native (MS) bitfield layout
diff -Naur a/src/gcc/config/arm/pe-stubs.c b/src/gcc/config/arm/pe-stubs.c
--- a/src/gcc/config/arm/pe-stubs.c	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/pe-stubs.c	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,52 @@
+/* Dummy subroutines for language-specific support on Windows.
+   Contributed by Danny Smith (dannysmith@users.sourceforge.net)
+   Copyright (C) 2005
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "hashtab.h"
+
+bool
+arm_pe_type_dllimport_p (tree decl ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+
+bool
+arm_pe_type_dllexport_p (tree decl ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+
+void
+arm_pe_adjust_class_at_definition (tree t ATTRIBUTE_UNUSED)
+{ }
diff -Naur a/src/gcc/config/arm/predicates.md b/src/gcc/config/arm/predicates.md
--- a/src/gcc/config/arm/predicates.md	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/predicates.md	2010-03-30 10:39:38.000000000 +0300
@@ -86,6 +86,12 @@
   (and (match_code "const_int")
        (match_test "const_ok_for_arm (INTVAL (op))")))
 
+;; A constant value which fits into two instructions, each taking
+;; an arithmetic constant operand for one of the words.
+(define_predicate "arm_immediate_di_operand"
+  (and (match_code "const_int,const_double")
+       (match_test "arm_const_double_by_immediates (op)")))
+
 (define_predicate "arm_neg_immediate_operand"
   (and (match_code "const_int")
        (match_test "const_ok_for_arm (-INTVAL (op))")))
@@ -115,6 +121,10 @@
   (ior (match_operand 0 "arm_rhs_operand")
        (match_operand 0 "arm_not_immediate_operand")))
 
+(define_predicate "arm_di_operand"
+  (ior (match_operand 0 "s_register_operand")
+       (match_operand 0 "arm_immediate_di_operand")))
+
 ;; True if the operand is a memory reference which contains an
 ;; offsettable address.
 (define_predicate "offsettable_memory_operand"
@@ -506,13 +516,15 @@
 (define_predicate "imm_for_neon_logic_operand"
   (match_code "const_vector")
 {
-  return neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL);
+  return (TARGET_NEON
+          && neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL));
 })
 
 (define_predicate "imm_for_neon_inv_logic_operand"
   (match_code "const_vector")
 {
-  return neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL);
+  return (TARGET_NEON
+          && neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL));
 })
 
 (define_predicate "neon_logic_op2"
@@ -528,3 +540,11 @@
   (and (match_code "const_int")
        (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
 
+;; Predicates for named expanders that overlap multiple ISAs.
+
+(define_predicate "cmpdi_operand"
+  (if_then_else (match_test "TARGET_HARD_FLOAT && TARGET_MAVERICK")
+		(and (match_test "TARGET_ARM")
+		     (match_operand 0 "cirrus_fp_register"))
+		(and (match_test "TARGET_32BIT")
+		     (match_operand 0 "arm_di_operand"))))
diff -Naur a/src/gcc/config/arm/sfp-machine.h b/src/gcc/config/arm/sfp-machine.h
--- a/src/gcc/config/arm/sfp-machine.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/sfp-machine.h	2010-04-13 10:45:12.000000000 +0300
@@ -94,7 +94,7 @@
 #define __fixdfdi	__aeabi_d2lz
 #define __fixunsdfdi	__aeabi_d2ulz
 #define __floatdidf	__aeabi_l2d
-#define __extendhfsf2	__gnu_h2f_ieee
-#define __truncsfhf2	__gnu_f2h_ieee
+#define __extendhfsf2	__aeabi_h2f
+#define __truncsfhf2	__aeabi_f2h
 
 #endif /* __ARM_EABI__ */
diff -Naur a/src/gcc/config/arm/symbian.h b/src/gcc/config/arm/symbian.h
--- a/src/gcc/config/arm/symbian.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/symbian.h	2010-03-30 10:39:38.000000000 +0300
@@ -71,11 +71,6 @@
 #define SUBTARGET_ASM_FLOAT_SPEC \
   "%{!mfpu=*:-mfpu=vfp} %{!mcpu=*:%{!march=*:-march=armv5t}}"
   
-/* SymbianOS provides the BPABI routines in a separate library.
-   Therefore, we do not need to define any of them in libgcc.  */
-#undef RENAME_LIBRARY
-#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) /* empty */
-
 /* Define the __symbian__ macro.  */
 #undef TARGET_OS_CPP_BUILTINS
 #define TARGET_OS_CPP_BUILTINS()				\
diff -Naur a/src/gcc/config/arm/t-cs-eabi b/src/gcc/config/arm/t-cs-eabi
--- a/src/gcc/config/arm/t-cs-eabi	2009-10-14 21:55:23.000000000 +0300
+++ b/src/gcc/config/arm/t-cs-eabi	2010-03-30 10:39:38.000000000 +0300
@@ -19,6 +19,7 @@
 MULTILIB_MATCHES      += march?armv7-a=mcpu?cortex-a5
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4f
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m4
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
 MULTILIB_MATCHES      += march?armv6-m=mcpu?cortex-m1
 MULTILIB_MATCHES      += march?armv6-m=mcpu?cortex-m0
diff -Naur a/src/gcc/config/arm/t-cs-eabi-lite b/src/gcc/config/arm/t-cs-eabi-lite
--- a/src/gcc/config/arm/t-cs-eabi-lite	2009-10-14 21:55:24.000000000 +0300
+++ b/src/gcc/config/arm/t-cs-eabi-lite	2010-03-30 10:39:38.000000000 +0300
@@ -22,6 +22,7 @@
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-a5
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4f
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m4
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
 
 MULTILIB_EXCEPTIONS   += march=armv6-m
diff -Naur a/src/gcc/config/arm/t-cs-uclinux-eabi b/src/gcc/config/arm/t-cs-uclinux-eabi
--- a/src/gcc/config/arm/t-cs-uclinux-eabi	2009-10-14 21:55:24.000000000 +0300
+++ b/src/gcc/config/arm/t-cs-uclinux-eabi	2010-03-30 10:39:38.000000000 +0300
@@ -28,6 +28,7 @@
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-a5
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4f
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m4
 MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
 
 MULTILIB_EXCEPTIONS   += march=armv6-m
diff -Naur a/src/gcc/config/arm/t-cygming b/src/gcc/config/arm/t-cygming
--- a/src/gcc/config/arm/t-cygming	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/t-cygming	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,10 @@
+# cygwin and mingw always have a limits.h, but, depending upon how we are
+# doing the build, it may not be installed yet.
+LIMITS_H_TEST = true
+
+# If we are building next to winsup, this will let us find the real
+# limits.h when building libgcc2.  Otherwise, winsup must be installed
+# first.
+LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/w32api/include
+
+STMP_FIXINC=stmp-fixinc
diff -Naur a/src/gcc/config/arm/thumb2.md b/src/gcc/config/arm/thumb2.md
--- a/src/gcc/config/arm/thumb2.md	2009-10-16 19:19:42.000000000 +0300
+++ b/src/gcc/config/arm/thumb2.md	2010-03-30 10:39:38.000000000 +0300
@@ -59,7 +59,7 @@
 			 [(match_operand:SI 2 "s_register_operand" "r")
 			  (match_operand:SI 3 "const_int_operand" "M")]))
 		(match_operand:SI 1 "s_register_operand" "r")))]
-  "TARGET_ARM"
+  "TARGET_THUMB2"
   "bic%?\\t%0, %1, %2%S4"
   [(set_attr "predicable" "yes")
    (set_attr "shift" "2")
@@ -310,8 +310,8 @@
   "
   [(set_attr "length" "8,12,16,8,8")
    (set_attr "type" "*,*,*,load2,store2")
-   (set_attr "pool_range" "1020")
-   (set_attr "neg_pool_range" "0")]
+   (set_attr "pool_range" "*,*,*,4096,*")
+   (set_attr "neg_pool_range" "*,*,*,0,*")]
 )
 
 (define_insn "*thumb2_cmpsi_shiftsi"
@@ -1089,9 +1089,9 @@
 )
 
 (define_insn "*thumb2_addsi_short"
-  [(set (match_operand:SI 0 "low_register_operand" "=l")
-	(plus:SI (match_operand:SI 1 "low_register_operand" "l")
-		 (match_operand:SI 2 "low_reg_or_int_operand" "lIL")))
+  [(set (match_operand:SI 0 "low_register_operand" "=l,l")
+	(plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
+		 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2 && reload_completed"
   "*
@@ -1109,7 +1109,7 @@
       return \"add%!\\t%0, %1, %2\";
   "
   [(set_attr "predicable" "yes")
-   (set_attr "length" "4")]
+   (set_attr "length" "2")]
 )
 
 (define_insn "*thumb2_subsi_short"
@@ -1123,6 +1123,56 @@
    (set_attr "length" "2")]
 )
 
+(define_insn "*thumb2_addsi3_compare0"
+  [(set (reg:CC_NOOV CC_REGNUM)
+	(compare:CC_NOOV
+	  (plus:SI (match_operand:SI 1 "s_register_operand" "l,  0, r")
+		   (match_operand:SI 2 "arm_add_operand"    "lPt,Ps,rIL"))
+	  (const_int 0)))
+   (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
+	(plus:SI (match_dup 1) (match_dup 2)))]
+  "TARGET_THUMB2"
+  "*
+    HOST_WIDE_INT val;
+
+    if (GET_CODE (operands[2]) == CONST_INT)
+      val = INTVAL (operands[2]);
+    else
+      val = 0;
+
+    if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
+      return \"subs\\t%0, %1, #%n2\";
+    else
+      return \"adds\\t%0, %1, %2\";
+  "
+  [(set_attr "conds" "set")
+   (set_attr "length" "2,2,4")]
+)
+
+(define_insn "*thumb2_addsi3_compare0_scratch"
+  [(set (reg:CC_NOOV CC_REGNUM)
+	(compare:CC_NOOV
+	  (plus:SI (match_operand:SI 0 "s_register_operand" "l,  r")
+		   (match_operand:SI 1 "arm_add_operand"    "lPu,rIL"))
+	  (const_int 0)))]
+  "TARGET_THUMB2"
+  "*
+    HOST_WIDE_INT val;
+
+    if (GET_CODE (operands[1]) == CONST_INT)
+      val = INTVAL (operands[1]);
+    else
+      val = 0;
+
+    if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
+      return \"cmp\\t%0, #%n1\";
+    else
+      return \"cmn\\t%0, %1\";
+  "
+  [(set_attr "conds" "set")
+   (set_attr "length" "2,4")]
+)
+
 ;; 16-bit encodings of "muls" and "mul<c>".  We only use these when
 ;; optimizing for size since "muls" is slow on all known
 ;; implementations and since "mul<c>" will be generated by
@@ -1182,7 +1232,7 @@
          (mult:SI (match_operand:SI 1 "register_operand" "%0")
 	          (match_operand:SI 2 "register_operand" "l"))
          (const_int 0)))
-   (clobber (match_scratch:SI 0 "=r"))]
+   (clobber (match_scratch:SI 0 "=l"))]
   "TARGET_THUMB2 && optimize_size"
   "muls\\t%0, %2, %0"
   [(set_attr "length" "2")
diff -Naur a/src/gcc/config/arm/t-mingw32 b/src/gcc/config/arm/t-mingw32
--- a/src/gcc/config/arm/t-mingw32	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/t-mingw32	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,2 @@
+# Match SYSTEM_INCLUDE_DIR
+NATIVE_SYSTEM_HEADER_DIR = /mingw/include
diff -Naur a/src/gcc/config/arm/t-nucleus b/src/gcc/config/arm/t-nucleus
--- a/src/gcc/config/arm/t-nucleus	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/arm/t-nucleus	2010-03-30 10:39:38.000000000 +0300
@@ -0,0 +1,3 @@
+
+# Add shared object crtstuff
+EXTRA_MULTILIB_PARTS += crtbeginS.o crtendS.o
diff -Naur a/src/gcc/config/arm/t-symbian b/src/gcc/config/arm/t-symbian
--- a/src/gcc/config/arm/t-symbian	2009-10-12 21:21:04.000000000 +0300
+++ b/src/gcc/config/arm/t-symbian	2010-03-30 10:39:38.000000000 +0300
@@ -1,25 +1,3 @@
-LIB1ASMFUNCS = _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
-
-# These functions have __aeabi equivalents and will never be called by GCC.  
-# By putting them in LIB1ASMFUNCS, we avoid the standard libgcc2.c code being
-# used -- and we make sure that definitions are not available in lib1funcs.asm,
-# either, so they end up undefined.
-LIB1ASMFUNCS += \
-	_ashldi3 _ashrdi3 _divdi3 _floatdidf _udivmoddi4 _umoddi3 \
-	_udivdi3 _lshrdi3 _moddi3 _muldi3 _negdi2 _cmpdi2 \
-	_fixdfdi _fixsfdi _fixunsdfdi _fixunssfdi _floatdisf \
-	_negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
-	_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
-	_fixsfsi _fixunssfsi
-
-# Include the gcc personality routine
-UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
-LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
-LIB2ADDEHDEP = $(UNWIND_H)
-
-# Include half-float helpers.
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
-
 # Create a multilib for processors with VFP floating-point, and a
 # multilib for those without -- using the soft-float ABI in both
 # cases.  Symbian OS object should be compiled with interworking
@@ -27,6 +5,9 @@
 MULTILIB_OPTIONS     = mfloat-abi=softfp
 MULTILIB_DIRNAMES    = softfp
 
+LIB2FUNCS_EXTRA += $(srcdir)/config/arm/eabi-memcpy.c \
+  $(srcdir)/config/arm/eabi-memset.c
+
 # There is no C library to link against on Symbian OS -- at least when 
 # building GCC.
 SHLIB_LC = 
diff -Naur a/src/gcc/config/arm/t-wince-pe b/src/gcc/config/arm/t-wince-pe
--- a/src/gcc/config/arm/t-wince-pe	2009-10-12 21:21:04.000000000 +0300
+++ b/src/gcc/config/arm/t-wince-pe	2010-03-30 10:39:38.000000000 +0300
@@ -1,5 +1,50 @@
 LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
+
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX \
+	_bb_init_func _lshrdi3 _ashrdi3 _ashldi3 \
+	_negdf2 _arm_addsubdf3 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
+	_arm_fixdfsi _arm_fixunsdfsi \
+	_arm_truncdfsf2 _arm_negsf2 _arm_addsubsf3 _arm_muldivsf3 _arm_cmpsf2 _arm_unordsf2 \
+	_arm_fixsfsi _arm_fixunssfsi _arm_floatdidf _arm_floatdisf \
+	_clzsi2 _clzdi2
+
+#
+# Filter out functions from dp-bit.c that are already in lib1funcs.asm
+#
+DPBIT_FUNCS := $(filter-out _mul_df _div_df _addsub_df _compare_df \
+	_eq_df _ne_df _gt_df _ge_df _lt_df _le_df \
+	_negate_df _unord_df \
+	_df_to_sf _si_to_df _df_to_si _usi_to_df, $(DPBIT_FUNCS))
+FPBIT_FUNCS := $(filter-out _mul_sf _div_sf _addsub_sf _compare_sf \
+	_eq_sf _ne_sf _gt_sf _ge_sf _lt_sf _le_sf \
+	_negate_sf _unord_sf \
+	_sf_to_df _si_to_sf _sf_to_si _usi_to_sf, $(FPBIT_FUNCS))
+
+LIB2FUNCS_EXCLUDE = _floatundisf _floatundidf _floatdidf _floatdisf \
+	_fixunssfsi _fixunsdfsi
+
+#LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX \
+#	_bb_init_func _lshrdi3 _ashrdi3 _ashldi3 \
+#	_arm_negdf2 _arm_addsubdf3 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
+#	_arm_fixdfsi _arm_fixunsdfsi \
+#	_arm_truncdfsf2 _arm_negsf2 _arm_addsubsf3 _arm_muldivsf3 _arm_cmpsf2 _arm_unordsf2 \
+#	_arm_fixsfsi _arm_fixunssfsi _arm_floatdidf _arm_floatdisf \
+#	_arm_fixunsdfsi \
+#	_clzsi2 _clzdi2
+
+# For most CPUs we have an assembly soft-float implementations.
+# However this is not true for ARMv6M.  Here we want to use the soft-fp C
+# implementation.  The soft-fp code is only build for ARMv6M.  This pulls
+# in the asm implementation for other CPUs.
+#LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
+#	_call_via_rX _interwork_call_via_rX \
+#	_lshrdi3 _ashrdi3 _ashldi3 \
+#	_arm_negdf2 _arm_addsubdf3 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
+#	_arm_fixdfsi _arm_fixunsdfsi \
+#	_arm_truncdfsf2 _arm_negsf2 _arm_addsubsf3 _arm_muldivsf3 \
+#	_arm_cmpsf2 _arm_unordsf2 _arm_fixsfsi _arm_fixunssfsi \
+#	_arm_floatdidf _arm_floatdisf _arm_floatundidf _arm_floatundisf \
+#	_clzsi2 _clzdi2
 
 # We want fine grained libraries, so use the new code to build the
 # floating point emulation libraries.
@@ -20,12 +65,34 @@
 	echo '#endif' >> dp-bit.c
 	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
 
-pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-  $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
-	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
+pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+  $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	$(srcdir)/config/arm/pe.c
+
+pe-cxx.o: $(srcdir)/config/arm/pe-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+  $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	$(srcdir)/config/arm/pe-cxx.c
+
+pe-stubs.o: $(srcdir)/config/arm/pe-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+  $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	$(srcdir)/config/arm/pe-stubs.c
+
+#hack! using i386 file directly...
+msformat-c.o: $(srcdir)/config/i386/msformat-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+  $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	$(srcdir)/config/i386/msformat-c.c
+
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
 
-MULTILIB_OPTIONS = mhard-float
-MULTILIB_DIRNAMES = fpu
 # Note - Thumb multilib omitted because Thumb support for
 # arm-wince-pe target does not appear to be working in binutils
 # yet... 
@@ -34,4 +101,65 @@
 
 LIBGCC = stmp-multilib
 INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS = 
+# Currently there is a bug somewhere in GCC's alias analysis
+# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
+# Disabling function inlining is a workaround for this problem.
+TARGET_LIBGCC2_CFLAGS = -fno-inline
+
+STMP_FIXINC=stmp-fixinc
+
+# Build a shared libgcc library for PECOFF with a DEF file
+# with the GNU linker.
+#
+# mkmap-flat.awk is used with the pe_dll option to produce a DEF instead
+# of an ELF map file.
+#
+# Warning: If SHLIB_SOVERSION or SHLIB_SONAME are updated, LIBGCC_SONAME
+# in mingw32.h and SHLIB_MKMAP_OPTS below must be updated also.
+
+SHLIB_EXT = .dll
+SHLIB_IMPLIB = @shlib_base_name@.a
+SHLIB_SOVERSION = 1
+SHLIB_SONAME = @shlib_base_name@_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
+SHLIB_MAP = @shlib_map_file@
+SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@/shlib
+SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+
+# Version for mingw32ce
+SHLIB_LC = -lmingw32 -lmingwex -lceoldname -lcoredll
+# Version for cegcc
+#SHLIB_LC = -lc -lcoredll
+
+# This should go somewhere else.
+# We are using SjLj EH.
+EH_MODEL = sjlj
+
+SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
+	if [ ! -d $(SHLIB_DIR) ]; then \
+		mkdir $(SHLIB_DIR); \
+	else true; fi && \
+	$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+	$(SHLIB_MAP).def \
+	-Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
+	-o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
+	$(SHLIB_OBJS) $(SHLIB_LC) && \
+	if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
+	  mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
+		$(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
+	else true; fi && \
+	mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
+	mv $(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp $(SHLIB_DIR)/$(SHLIB_IMPLIB)
+# $(slibdir) double quoted to protect it from expansion while building
+# libgcc.mk.  We want this delayed until actual install time.
+SHLIB_INSTALL = \
+	$$(mkinstalldirs) $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+	$(INSTALL_PROGRAM) $(SHLIB_DIR)/$(SHLIB_SONAME) \
+	  $$(DESTDIR)$$(bindir)/$(SHLIB_SONAME); \
+	$(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_IMPLIB) \
+	  $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_IMPLIB)
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
+# We'd like to use SHLIB_SONAME here too, but shlib_base_name
+# does not get substituted before mkmap-flat.awk is run.
+SHLIB_MKMAP_OPTS = -v pe_dll=libgcc_s_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
+SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver
diff -Naur a/src/gcc/config/arm/t-wrs-linux b/src/gcc/config/arm/t-wrs-linux
--- a/src/gcc/config/arm/t-wrs-linux	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/t-wrs-linux	2010-03-31 10:34:43.000000000 +0300
@@ -19,23 +19,16 @@
 # <http://www.gnu.org/licenses/>.
 
 MULTILIB_OPTIONS = muclibc
-MULTILIB_OPTIONS += tarm926ej-s/tiwmmxt/txscale/tarm920t/tthumb2/tcortex-a8-be8
+MULTILIB_OPTIONS += tarm926ej-s/tthumb2-v7-a/tthumb2-v7-a-neon
 MULTILIB_OPTIONS += mfloat-abi=softfp
 MULTILIB_DIRNAMES = uclibc
-MULTILIB_DIRNAMES += tarm926ej-s tiwmmxt txscale tarm920t thumb2 cortex-a8-be8
+MULTILIB_DIRNAMES += tarm926ej-s thumb2-v7-a thumb2-v7-a-neon
 MULTILIB_DIRNAMES += softfp
 
-MULTILIB_EXCEPTIONS = *muclibc*/*tarm920t*
-MULTILIB_EXCEPTIONS += *muclibc*/*cortex-a8-be8*
-
-MULTILIB_EXCEPTIONS += *tiwmmxt*/*mfloat-abi=softfp*
-MULTILIB_EXCEPTIONS += *txscale*/*mfloat-abi=softfp*
-MULTILIB_EXCEPTIONS += *tarm920t*/*mfloat-abi=softfp*
 MULTILIB_EXCEPTIONS += *thumb2*/*mfloat-abi=softfp*
 
-MULTILIB_MATCHES = tiwmmxt=tiwmmxt2
-
-MULTILIB_ALIASES = tcortex-a8-be8=tcortex-a8-be8/mfloat-abi?softfp
+MULTILIB_ALIASES = tthumb2-v7-a-neon=tthumb2-v7-a-neon/mfloat-abi?softfp
+MULTILIB_ALIASES += muclibc/tthumb2-v7-a-neon=muclibc/tthumb2-v7-a-neon/mfloat-abi?softfp
 MULTILIB_OSDIRNAMES =
 
 # These files must be built for each multilib.
diff -Naur a/src/gcc/config/arm/vec-common.md b/src/gcc/config/arm/vec-common.md
--- a/src/gcc/config/arm/vec-common.md	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/vec-common.md	2010-03-30 10:39:38.000000000 +0300
@@ -42,6 +42,11 @@
     {
       if (GET_CODE (operands[0]) != REG)
 	operands[1] = force_reg (<MODE>mode, operands[1]);
+      else if (TARGET_NEON && CONSTANT_P (operands[1]))
+	{
+	  operands[1] = neon_make_constant (operands[1]);
+	  gcc_assert (operands[1] != NULL_RTX);
+	}
     }
 })
 
diff -Naur a/src/gcc/config/arm/vfp.md b/src/gcc/config/arm/vfp.md
--- a/src/gcc/config/arm/vfp.md	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/vfp.md	2010-04-09 10:32:04.000000000 +0300
@@ -135,9 +135,51 @@
 ;; DImode moves
 
 (define_insn "*arm_movdi_vfp"
-  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv")
+  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, m,w,r,w,w, Uv")
 	(match_operand:DI 1 "di_operand"              "rIK,mi,r,r,w,w,Uvi,w"))]
-  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
+  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune != cortexa8
+   && (   register_operand (operands[0], DImode)
+       || register_operand (operands[1], DImode))"
+  "*
+  switch (which_alternative)
+    {
+    case 0: 
+      return \"#\";
+    case 1:
+    case 2:
+      return output_move_double (operands);
+    case 3:
+      return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
+    case 4:
+      return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
+    case 5:
+      if (TARGET_VFP_SINGLE)
+	return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\";
+      else
+	return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
+    case 6: case 7:
+      return output_move_vfp (operands);
+    default:
+      gcc_unreachable ();
+    }
+  "
+  [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
+   (set_attr "neon_type" "*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*")
+   (set (attr "length") (cond [(eq_attr "alternative" "0,1,2") (const_int 8)
+			       (eq_attr "alternative" "5")
+				(if_then_else
+				 (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1))
+				 (const_int 8)
+				 (const_int 4))]
+			      (const_int 4)))
+   (set_attr "pool_range"     "*,1020,*,*,*,*,1020,*")
+   (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
+)
+
+(define_insn "*arm_movdi_vfp_cortexa8"
+  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,!r,w,w, Uv")
+	(match_operand:DI 1 "di_operand"              "rIK,mi,r,r,w,w,Uvi,w"))]
+  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune == cortexa8
    && (   register_operand (operands[0], DImode)
        || register_operand (operands[1], DImode))"
   "*
@@ -403,8 +445,8 @@
 ;; DFmode moves
 
 (define_insn "*movdf_vfp"
-  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,r, m,w  ,Uv,w,r")
-	(match_operand:DF 1 "soft_df_operand"		   " ?r,w,Dy,mF,r,UvF,w, w,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w, r, m,w  ,Uv,w,r")
+	(match_operand:DF 1 "soft_df_operand"		   " ?r,w,Dy,D0,mF,r,UvF,w, w,r"))]
   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
    && (   register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
@@ -419,16 +461,18 @@
       case 2:
 	gcc_assert (TARGET_VFP_DOUBLE);
         return \"fconstd%?\\t%P0, #%G1\";
-      case 3: case 4:
+      case 3:
+	return \"vmov.i32\\t%P0, #0\";
+      case 4: case 5:
 	return output_move_double (operands);
-      case 5: case 6:
+      case 6: case 7:
 	return output_move_vfp (operands);
-      case 7:
+      case 8:
 	if (TARGET_VFP_SINGLE)
 	  return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
 	else
 	  return \"fcpyd%?\\t%P0, %P1\";
-      case 8:
+      case 9:
         return \"#\";
       default:
 	gcc_unreachable ();
@@ -436,23 +480,25 @@
     }
   "
   [(set_attr "type"
-     "r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*")
-   (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*")
-   (set (attr "length") (cond [(eq_attr "alternative" "3,4,8") (const_int 8)
-			       (eq_attr "alternative" "7")
+     "r_2_f,f_2_r,fconstd,*,f_loadd,f_stored,load2,store2,ffarithd,*")
+   (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,neon_vmov,*,*,*,*,neon_vmov,*")
+   (set (attr "length") (cond [(eq_attr "alternative" "4,5,9") (const_int 8)
+			       (eq_attr "alternative" "8")
 				(if_then_else
 				 (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1))
 				 (const_int 8)
 				 (const_int 4))]
 			      (const_int 4)))
-   (set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*")
-   (set_attr "neg_pool_range" "*,*,*,1008,*,1008,*,*,*")]
+   (set_attr "pool_range" "*,*,*,*,1020,*,1020,*,*,*")
+   (set_attr "neg_pool_range" "*,*,*,*,1008,*,1008,*,*,*")]
 )
 
 (define_insn "*thumb2_movdf_vfp"
-  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,r, m,w  ,Uv,w,r")
-	(match_operand:DF 1 "soft_df_operand"		   " ?r,w,Dy,mF,r,UvF,w, w,r"))]
-  "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
+  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w, r, m,w  ,Uv,w,r")
+	(match_operand:DF 1 "soft_df_operand"		   " ?r,w,Dy,D0,mF,r,UvF,w, w,r"))]
+  "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP
+   && (   register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode))"
   "*
   {
     switch (which_alternative)
@@ -464,11 +510,13 @@
       case 2:
 	gcc_assert (TARGET_VFP_DOUBLE);
 	return \"fconstd%?\\t%P0, #%G1\";
-      case 3: case 4: case 8:
+      case 3:
+	return \"vmov.i32\\t%P0, #0\";
+      case 4: case 5: case 9:
 	return output_move_double (operands);
-      case 5: case 6:
+      case 6: case 7:
 	return output_move_vfp (operands);
-      case 7:
+      case 8:
 	if (TARGET_VFP_SINGLE)
 	  return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
 	else
@@ -479,17 +527,17 @@
     }
   "
   [(set_attr "type"
-     "r_2_f,f_2_r,fconstd,load2,store2,f_load,f_store,ffarithd,*")
-   (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*")
-   (set (attr "length") (cond [(eq_attr "alternative" "3,4,8") (const_int 8)
-			       (eq_attr "alternative" "7")
+     "r_2_f,f_2_r,fconstd,*,load2,store2,f_load,f_store,ffarithd,*")
+   (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,neon_vmov,*,*,*,*,neon_vmov,*")
+   (set (attr "length") (cond [(eq_attr "alternative" "4,5,9") (const_int 8)
+			       (eq_attr "alternative" "8")
 				(if_then_else
 				 (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1))
 				 (const_int 8)
 				 (const_int 4))]
 			      (const_int 4)))
-   (set_attr "pool_range" "*,*,*,4096,*,1020,*,*,*")
-   (set_attr "neg_pool_range" "*,*,*,0,*,1008,*,*,*")]
+   (set_attr "pool_range" "*,*,*,*,4096,*,1020,*,*,*")
+   (set_attr "neg_pool_range" "*,*,*,*,0,*,1008,*,*,*")]
 )
 
 
diff -Naur a/src/gcc/config/arm/wince-pe.h b/src/gcc/config/arm/wince-pe.h
--- a/src/gcc/config/arm/wince-pe.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/wince-pe.h	2010-03-30 10:39:38.000000000 +0300
@@ -1,7 +1,11 @@
-/* Definitions of target machine for GNU compiler, for ARM with WINCE-PE obj format.
+/* Definitions of target machine for GNU compiler, for ARM with
+   WINCE-PE obj format.
+
    Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
    Contributed by Nick Clifton <nickc@redhat.com>
-   
+
+   Further development by Pedro Alves <pedro_alves@portugalmail.pt>
+
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
@@ -18,9 +22,243 @@
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
-#undef  TARGET_DEFAULT
-#define TARGET_DEFAULT	(MASK_NOP_FUN_DLLIMPORT)
+/* Enable WinCE specific code.  */
+#define ARM_WINCE 1
+
+#undef MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#define TARGET_EXECUTABLE_SUFFIX ".exe"
+
+#undef  TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (arm Windows CE/Native SDK)");
+
+#undef SUBTARGET_CONDITIONAL_REGISTER_USAGE
+#define SUBTARGET_CONDITIONAL_REGISTER_USAGE
 
 #undef  MULTILIB_DEFAULTS
 #define MULTILIB_DEFAULTS \
-  { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }  
+  { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
+
+#undef SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm8
+
+/* We must store doubles in little endian order.  Specifying the
+   default of VFP assures that.  To guaranty VFP insns won't be
+   emitted by default, we default to float-abi=soft.  */
+#undef  FPUTYPE_DEFAULT
+#define FPUTYPE_DEFAULT "vfp"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu) \
+-DWIN32 -D_WIN32 -D__WIN32 -D__WIN32__ \
+%{!nostdinc: -idirafter ../include/w32api%s -idirafter ../../include/w32api%s } \
+"
+
+#ifndef ASM_SPEC
+#define ASM_SPEC "\
+%{mbig-endian:-EB} \
+%{mlittle-endian:-EL} \
+%{mcpu=*:-mcpu=%*} \
+%{march=*:-march=%*} \
+%{mapcs-*:-mapcs-%*} \
+%(subtarget_asm_float_spec) \
+%{mthumb-interwork:-mthumb-interwork} \
+%{msoft-float:-mfloat-abi=soft} %{mhard-float:-mfloat-abi=hard} \
+%{mfloat-abi=*} %{mfpu=*} \
+%(subtarget_extra_asm_spec)"
+#endif
+
+#define EXTRA_OS_CPP_BUILTINS()
+
+#define TARGET_OS_CPP_BUILTINS()					\
+  do									\
+  {									\
+      /* We currently define UNDER_CE to a non-value, as it seems	\
+         MSVC2005 does the same.  */ 					\
+      builtin_define_std ("UNDER_CE");					\
+      builtin_define ("_UNICODE");					\
+      builtin_define_std ("UNICODE");					\
+	  /* Let's just ignore stdcall, and fastcall.  */ 		\
+      builtin_define ("__stdcall=__attribute__((__cdecl__))");		\
+      builtin_define ("__fastcall=__attribute__((__cdecl__))");		\
+      builtin_define ("__cdecl=__attribute__((__cdecl__))");		\
+      if (!flag_iso)							\
+        {								\
+          builtin_define ("_stdcall=__attribute__((__cdecl__))");	\
+          builtin_define ("_fastcall=__attribute__((__cdecl__))");	\
+          builtin_define ("_cdecl=__attribute__((__cdecl__))");		\
+        }								\
+      /* Even though linkonce works with static libs, this is needed 	\
+          to compare typeinfo symbols across dll boundaries.  */	\
+      builtin_define ("__GXX_MERGED_TYPEINFO_NAMES=0");			\
+      builtin_define ("__GXX_TYPEINFO_EQUALITY_INLINE=0");		\
+      EXTRA_OS_CPP_BUILTINS ();						\
+      {                                                       		\
+        /* Define these to be compatible MSFT's tools.  */    		\
+        char buf[64];                                         		\
+        int arch = arm_major_arch ();                         		\
+        sprintf (buf, "_M_ARM=%d", arch);                     		\
+        builtin_define (buf);                                 		\
+        if (arm_thumb_arch_p ())                              		\
+          {                                                   		\
+            sprintf (buf, "_M_ARMT=%d", arch);                		\
+            builtin_define (buf);                            		\
+          }                                                   		\
+        /* Always defined as empty.  */                       		\
+        builtin_define ("ARM=");                              		\
+      }                                                       		\
+  }                                                           		\
+  while (0)
+
+/* Now we define the strings used to build the spec file.  */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
+
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "-lgcc"
+
+/* Link with coredll, the main libc in the native SDK, and with
+   corelibc, a static lib that contains the start files, among other
+   basic crt stuff.  */
+
+#undef LIB_SPEC
+#define LIB_SPEC "-lcoredll -lcorelibc"
+
+#undef LINK_SPEC
+#define LINK_SPEC "\
+  %{shared: %{mdll: %eshared and mdll are not compatible}} \
+  %{shared: --shared} %{mdll:--dll} \
+  %{static:-Bstatic} %{!static:-Bdynamic} \
+  %{shared|mdll: -e DllMainCRTStartup} \
+  "
+
+
+/* Don't assume anything about the header files.  */
+#define NO_IMPLICIT_EXTERN_C
+
+
+/* Define types for compatibility with MS runtime.  */
+
+#undef DEFAULT_SIGNED_CHAR
+#define DEFAULT_SIGNED_CHAR 1
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+
+#undef WINT_TYPE
+#define WINT_TYPE "short unsigned int"
+
+
+#undef DWARF2_UNWIND_INFO
+#define DWARF2_UNWIND_INFO 0
+
+#define DWARF2_DEBUGGING_INFO 1
+
+#undef  PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#undef HAVE_AS_DWARF2_DEBUG_LINE
+#define HAVE_AS_DWARF2_DEBUG_LINE 1
+
+/* Use section relative relocations for debugging offsets.  Unlike
+   other targets that fake this by putting the section VMA at 0, PE
+   won't allow it.  */
+#define ASM_OUTPUT_DWARF_OFFSET(FILE, SIZE, LABEL, SECTION)    \
+  do {                                                \
+    if (SIZE != 4)                                    \
+      abort ();                                       \
+                                                      \
+    fputs ("\t.secrel32\t", FILE);                    \
+    assemble_name (FILE, LABEL);                      \
+  } while (0)
+
+/* Align output to a power of two.  Note ".align 0" is redundant,
+   and also GAS will treat it as ".align 2" which we do not want.  */
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(STREAM, POWER)			\
+  do							\
+    {							\
+      if ((POWER) > 0)					\
+	fprintf (STREAM, "\t.align\t%d\n", POWER);	\
+    }							\
+  while (0)
+
+/* Prefix for internally generated assembler labels.  If we aren't using
+   underscores, we are using prefix `.'s to identify labels that should
+   be ignored.  */
+/* If user-symbols don't have underscores,
+   then it must take more than `L' to identify
+   a label that should be ignored.  */
+
+#undef  LPREFIX
+#define LPREFIX ".L"
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* The prefix to add to user-visible assembler symbols.
+   Arm Windows CE is not underscored.  */
+
+#undef  USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* This is how to store into the string BUF
+   the symbol_ref name of an internal numbered label where
+   PREFIX is the class of label and NUM is the number within the class.
+   This is suitable for output with `assemble_name'.  */
+#undef  ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER)	\
+  sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
+
+/* We have to re-define this to prevent any conflicts.  */
+#undef ARM_MCOUNT_NAME
+#define ARM_MCOUNT_NAME "_mcount"
+
+
+/* Emit code to check the stack when allocating more than 4000
+   bytes in one go.  */
+/*#define CHECK_STACK_LIMIT 4000 */
+
+
+
+/* We do bitfields MSVC-compatibly by default.
+   We choose to be compatible with Microsoft's ARM and Thumb compilers,
+   which always return aggregates in memory.  */
+
+/* TODO: Maybe add MASK_STACK_PROBE ? and enable CHECK_STACK_LIMIT?  */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_NOP_FUN_DLLIMPORT | \
+                        MASK_MS_BITFIELD_LAYOUT)
+
+/* A bit-field declared as `int' forces `int' alignment for the struct.  */
+#undef PCC_BITFIELD_TYPE_MATTERS
+#define PCC_BITFIELD_TYPE_MATTERS 1
+#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
+
+#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
+#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
+
+#undef ARM_DOUBLEWORD_ALIGN
+#define ARM_DOUBLEWORD_ALIGN 0
+
+#undef BIGGEST_ALIGNMENT
+#define BIGGEST_ALIGNMENT 64
+
+/* defined in pe.h */
+#undef SYSV_PRAGMA
+
+#undef TREE
+
+#ifndef BUFSIZ
+# undef FILE
+#endif
diff -Naur a/src/gcc/config/arm/wrs-linux.h b/src/gcc/config/arm/wrs-linux.h
--- a/src/gcc/config/arm/wrs-linux.h	2009-10-12 21:21:03.000000000 +0300
+++ b/src/gcc/config/arm/wrs-linux.h	2010-03-31 10:34:43.000000000 +0300
@@ -27,15 +27,9 @@
 #undef CC1_SPEC
 #define CC1_SPEC "							\
  %{tarm926ej-s:	-mcpu=arm926ej-s ;					\
-   tiwmmxt:     -mcpu=iwmmxt ;						\
-   tiwmmxt2:    -mcpu=iwmmxt ;						\
-   txscale:     -mcpu=xscale -mbig-endian ;				\
-   tarm920t:    -mcpu=arm920t ;						\
-   tthumb2:     %{!mcpu=*:%{!march=*:-march=armv6t2}} -mthumb ;		\
-   tcortex-a8-be8: -mcpu=cortex-a8 -mbig-endian -mfloat-abi=softfp	\
-                   -mfpu=neon }						\
- %{txscale:%{mfloat-abi=softfp:%eXScale VFP multilib not provided}}	\
- %{tarm920t:%{mfloat-abi=softfp:%eARM920T VFP multilib not provided}}	\
+   tthumb2-v7-a: %{!mcpu=*:%{!march=*:-mcpu=cortex-a8}} -mthumb ;	\
+   tthumb2-v7-a-neon: %{!mcpu=*:%{!march=*:-mcpu=cortex-a8}}		\
+                      -mthumb -mfloat-abi=softfp -mfpu=neon }		\
  %{profile:-p}"
 
 /* Since the ARM926EJ-S is the default processor, we do not need to
@@ -50,27 +44,9 @@
 #define SYSROOT_HEADERS_SUFFIX_SPEC		\
   "%{muclibc:/uclibc}" 
 
-/* Translate -tiwmmxt appropriately for the assembler.  The -meabi=5
-   option is the relevant part of SUBTARGET_EXTRA_ASM_SPEC in bpabi.h.  */
-#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC \
-  "%{tiwmmxt2:-mcpu=iwmmxt2} %{tiwmmxt:-mcpu=iwmmxt} %{txscale:-mcpu=xscale -EB} %{tcortex-a8-be8:-mcpu=cortex-a8 -EB} -meabi=5" 
-
-/* Translate -tiwmmxt for the linker.  */
-#undef SUBTARGET_EXTRA_LINK_SPEC
-#define SUBTARGET_EXTRA_LINK_SPEC			\
-  " %{tiwmmxt:-m armelf_linux_eabi ;			\
-     txscale:-m armelfb_linux_eabi ;			\
-     tcortex-a8-be8:-m armelfb_linux_eabi %{!r:--be8} ;	\
-     : -m armelf_linux_eabi}"
-
 /* The various C libraries each have their own subdirectory.  */
 #undef SYSROOT_SUFFIX_SPEC
 #define SYSROOT_SUFFIX_SPEC					\
-  "%{muclibc:/uclibc}%{tiwmmxt:/tiwmmxt ;			\
-     tiwmmxt2:/tiwmmxt ;					\
-     txscale:/txscale ;						\
-     tarm920t:/tarm920t ;					\
-     tthumb2:/thumb2 ;						\
-     tcortex-a8-be8:/cortex-a8-be8}%{!tthumb2:%{!tcortex-a8-be8:%{mfloat-abi=softfp:/softfp}}}"
+  "%{muclibc:/uclibc}%{tthumb2-v7-a:/thumb2-v7-a ;		\
+     tthumb2-v7-a-neon:/thumb2-v7-a-neon}%{!tthumb2*:%{mfloat-abi=softfp:/softfp}}"
 
diff -Naur a/src/gcc/config/i386/gthr-win32.c b/src/gcc/config/i386/gthr-win32.c
--- a/src/gcc/config/i386/gthr-win32.c	2009-10-12 21:20:52.000000000 +0300
+++ b/src/gcc/config/i386/gthr-win32.c	2010-03-30 10:39:20.000000000 +0300
@@ -32,7 +32,9 @@
 # define __GTHREAD_HIDE_WIN32API 1
 #endif
 #undef  __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
+#ifdef __i386__
 #define __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
+#endif
 #include <gthr-win32.h>
 
 /* Windows32 threads specific definitions. The windows32 threading model
@@ -70,7 +72,11 @@
 __gthr_win32_once (__gthread_once_t *once, void (*func) (void))
 {
   if (once == NULL || func == NULL)
+#ifdef __MINGW32CE__
+    return -1;
+#else
     return EINVAL;
+#endif
 
   if (! once->done)
     {
diff -Naur a/src/gcc/config/sh/constraints.md b/src/gcc/config/sh/constraints.md
--- a/src/gcc/config/sh/constraints.md	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/constraints.md	2010-03-30 10:39:22.000000000 +0300
@@ -22,6 +22,7 @@
 ;;  Bsc: SCRATCH - for the scratch register in movsi_ie in the
 ;;       fldi0 / fldi0 cases
 ;; Cxx: Constants other than only CONST_INT
+;;  Ccl: call site label
 ;;  Css: signed 16-bit constant, literal or symbolic
 ;;  Csu: unsigned 16-bit constant, literal or symbolic
 ;;  Csy: label or symbol
@@ -183,6 +184,11 @@
    hence mova is being used, hence do not select this pattern."
   (match_code "scratch"))
 
+(define_constraint "Ccl"
+  "A call site label, for bsrf."
+  (and (match_code "unspec")
+       (match_test "XINT (op, 1) == UNSPEC_CALLER")))
+
 (define_constraint "Css"
   "A signed 16-bit constant, literal or symbolic."
   (and (match_code "const")
diff -Naur a/src/gcc/config/sh/lib1funcs.asm b/src/gcc/config/sh/lib1funcs.asm
--- a/src/gcc/config/sh/lib1funcs.asm	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/lib1funcs.asm	2010-03-30 10:39:22.000000000 +0300
@@ -1968,7 +1968,10 @@
 	HIDDEN_FUNC(GLOBAL(set_fpscr))
 GLOBAL(set_fpscr):
 	lds r4,fpscr
-#ifdef __PIC__
+#if defined(__SH_FDPIC__)
+	mov.l	LOCAL(set_fpscr_L1),r0
+	mov.l	@(r0,r12),r1
+#elif defined(__PIC__)
 	mov.l	r12,@-r15
 #ifdef __vxworks
 	mov.l	LOCAL(set_fpscr_L0_base),r12
@@ -2014,6 +2017,7 @@
 #endif
 	.align 2
 #ifdef __PIC__
+#ifndef __SH_FDPIC__
 #ifdef __vxworks
 LOCAL(set_fpscr_L0_base):
 	.long ___GOTT_BASE__
@@ -2023,6 +2027,7 @@
 LOCAL(set_fpscr_L0):
 	.long _GLOBAL_OFFSET_TABLE_
 #endif
+#endif /* __SH_FDPIC__ */
 LOCAL(set_fpscr_L1):
 	.long GLOBAL(fpscr_values@GOT)
 #else
diff -Naur a/src/gcc/config/sh/sh.c b/src/gcc/config/sh/sh.c
--- a/src/gcc/config/sh/sh.c	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/sh.c	2010-03-30 10:39:22.000000000 +0300
@@ -233,6 +233,7 @@
 static rtx sh_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
 static void sh_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
 static void sh_file_start (void);
+static bool sh_assemble_integer (rtx, unsigned, int);
 static int flow_dependent_p (rtx, rtx);
 static void flow_dependent_p_1 (rtx, const_rtx, void *);
 static int shiftcosts (rtx);
@@ -272,6 +273,7 @@
 static int sh_dwarf_calling_convention (const_tree);
 static void sh_encode_section_info (tree, rtx, int);
 static int sh2a_function_vector_p (tree);
+static int sh_reloc_rw_mask (void);
 
 
 /* Initialize the GCC target structure.  */
@@ -304,6 +306,9 @@
 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
 
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER sh_assemble_integer
+
 #undef TARGET_DEFAULT_TARGET_FLAGS
 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
 #undef TARGET_HANDLE_OPTION
@@ -483,6 +488,12 @@
 /* Machine-specific symbol_ref flags.  */
 #define SYMBOL_FLAG_FUNCVEC_FUNCTION    (SYMBOL_FLAG_MACH_DEP << 0)
 
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM sh_illegitimate_symbolic_constant_p
+
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK sh_reloc_rw_mask
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -1132,11 +1143,13 @@
 	  rtx func_addr_rtx = gen_reg_rtx (Pmode);
 	  rtx r4 = gen_rtx_REG (SImode, 4);
 	  rtx r5 = gen_rtx_REG (SImode, 5);
+	  rtx lab;
 
-	  function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC);
+	  function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC,
+			   &lab);
 	  force_into (XEXP (operands[0], 0), r4);
 	  force_into (XEXP (operands[1], 0), r5);
-	  emit_insn (gen_block_move_real_i4 (func_addr_rtx));
+	  emit_insn (gen_block_move_real_i4 (func_addr_rtx, lab));
 	  return 1;
 	}
       else if (! TARGET_SMALLCODE)
@@ -1147,15 +1160,16 @@
 	  rtx r4 = gen_rtx_REG (SImode, 4);
 	  rtx r5 = gen_rtx_REG (SImode, 5);
 	  rtx r6 = gen_rtx_REG (SImode, 6);
+	  rtx lab;
 
 	  entry_name = (bytes & 4 ? "__movmem_i4_odd" : "__movmem_i4_even");
-	  function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC);
+	  function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC, &lab);
 	  force_into (XEXP (operands[0], 0), r4);
 	  force_into (XEXP (operands[1], 0), r5);
 
 	  dwords = bytes >> 3;
 	  emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
-	  emit_insn (gen_block_lump_real_i4 (func_addr_rtx));
+	  emit_insn (gen_block_lump_real_i4 (func_addr_rtx, lab));
 	  return 1;
 	}
       else
@@ -1167,12 +1181,13 @@
       rtx func_addr_rtx = gen_reg_rtx (Pmode);
       rtx r4 = gen_rtx_REG (SImode, 4);
       rtx r5 = gen_rtx_REG (SImode, 5);
+      rtx lab;
 
       sprintf (entry, "__movmemSI%d", bytes);
-      function_symbol (func_addr_rtx, entry, SFUNC_STATIC);
+      function_symbol (func_addr_rtx, entry, SFUNC_STATIC, &lab);
       force_into (XEXP (operands[0], 0), r4);
       force_into (XEXP (operands[1], 0), r5);
-      emit_insn (gen_block_move_real (func_addr_rtx));
+      emit_insn (gen_block_move_real (func_addr_rtx, lab));
       return 1;
     }
 
@@ -1185,8 +1200,9 @@
       rtx r4 = gen_rtx_REG (SImode, 4);
       rtx r5 = gen_rtx_REG (SImode, 5);
       rtx r6 = gen_rtx_REG (SImode, 6);
+      rtx lab;
 
-      function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC);
+      function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC, &lab);
       force_into (XEXP (operands[0], 0), r4);
       force_into (XEXP (operands[1], 0), r5);
 
@@ -1199,7 +1215,7 @@
       final_switch = 16 - ((bytes / 4) % 16);
       while_loop = ((bytes / 4) / 16 - 1) * 16;
       emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
-      emit_insn (gen_block_lump_real (func_addr_rtx));
+      emit_insn (gen_block_lump_real (func_addr_rtx, lab));
       return 1;
     }
 
@@ -1212,8 +1228,10 @@
 int
 prepare_move_operands (rtx operands[], enum machine_mode mode)
 {
+  rtx tmp, base, offset;
+
   if ((mode == SImode || mode == DImode)
-      && flag_pic
+      && (flag_pic || TARGET_FDPIC)
       && ! ((mode == Pmode || mode == ptr_mode)
 	    && tls_symbolic_operand (operands[1], Pmode) != 0))
     {
@@ -1303,12 +1321,22 @@
 	    {
 	    case TLS_MODEL_GLOBAL_DYNAMIC:
 	      tga_ret = gen_rtx_REG (Pmode, R0_REG);
+	      if (TARGET_FDPIC)
+		{
+		  rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+		  emit_move_insn (pic_reg, OUR_FDPIC_REG);
+		}
 	      emit_call_insn (gen_tls_global_dynamic (tga_ret, op1));
 	      op1 = tga_ret;
 	      break;
 
 	    case TLS_MODEL_LOCAL_DYNAMIC:
 	      tga_ret = gen_rtx_REG (Pmode, R0_REG);
+	      if (TARGET_FDPIC)
+		{
+		  rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+		  emit_move_insn (pic_reg, OUR_FDPIC_REG);
+		}
 	      emit_call_insn (gen_tls_local_dynamic (tga_ret, op1));
 
 	      tmp = gen_reg_rtx (Pmode);
@@ -1338,6 +1366,11 @@
 		}
 	      tga_op1 = !can_create_pseudo_p () ? op0 : gen_reg_rtx (Pmode);
 	      tmp = gen_sym2GOTTPOFF (op1);
+	      if (TARGET_FDPIC)
+		{
+		  rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+		  emit_move_insn (pic_reg, OUR_FDPIC_REG);
+		}
 	      emit_insn (gen_tls_initial_exec (tga_op1, tmp));
 	      op1 = tga_op1;
 	      break;
@@ -1365,6 +1398,21 @@
 	}
     }
 
+  if (SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+    {
+      split_const (operands[1], &base, &offset);
+      if (GET_CODE (base) == SYMBOL_REF
+	  && !offset_within_block_p (base, INTVAL (offset)))
+	{
+	  tmp = can_create_pseudo_p () ? gen_reg_rtx (mode) : operands[0];
+	  emit_move_insn (tmp, base);
+	  if (!arith_operand (offset, mode))
+	    offset = force_reg (mode, offset);
+	  emit_insn (gen_add3_insn (operands[0], tmp, offset));
+	  return 1;
+	}
+    }
+
   return 0;
 }
 
@@ -2147,6 +2195,26 @@
     }
 }
 
+/* Implementation of TARGET_ASM_INTEGER for SH.  Pointers to functions
+   need to be output as pointers to function descriptors for
+   FDPIC.  */
+
+static bool
+sh_assemble_integer (rtx value, unsigned int size, int aligned_p)
+{
+  if (TARGET_FDPIC
+      && size == UNITS_PER_WORD
+      && GET_CODE (value) == SYMBOL_REF
+      && SYMBOL_REF_FUNCTION_P (value))
+    {
+      fputs ("\t.long\t", asm_out_file);
+      output_addr_const (asm_out_file, value);
+      fputs ("@FUNCDESC\n", asm_out_file);
+      return true;
+    }
+  return default_assemble_integer (value, size, aligned_p);
+}
+
 /* Check if PAT includes UNSPEC_CALLER unspec pattern.  */
 
 static bool
@@ -2175,7 +2243,7 @@
 {
   rtx pat;
 
-  if (!reload_completed || !flag_pic)
+  if (!reload_completed || (!flag_pic && !TARGET_FDPIC))
     return false;
 
   if (GET_CODE (insn) != INSN)
@@ -2714,6 +2782,7 @@
   rtx wrk;
   char func[18];
   int value;
+  rtx lab;
 
   if (TARGET_SH3)
     {
@@ -2779,8 +2848,8 @@
   /* Load the value into an arg reg and call a helper.  */
   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
   sprintf (func, "__ashiftrt_r4_%d", value);
-  function_symbol (wrk, func, SFUNC_STATIC);
-  emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk));
+  function_symbol (wrk, func, SFUNC_STATIC, &lab);
+  emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk, lab));
   emit_move_insn (operands[0], gen_rtx_REG (SImode, 4));
   return 1;
 }
@@ -6508,7 +6577,9 @@
   else
     push_regs (&live_regs_mask, current_function_interrupt);
 
-  if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
+  if (flag_pic
+      && !TARGET_FDPIC
+      && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
     emit_insn (gen_GOTaddr2picreg ());
 
   if (SHMEDIA_REGS_STACK_ADJUST ())
@@ -6518,7 +6589,7 @@
       function_symbol (gen_rtx_REG (Pmode, R0_REG),
 		       (TARGET_FPU_ANY
 			? "__GCC_push_shmedia_regs"
-			: "__GCC_push_shmedia_regs_nofpu"), SFUNC_GOT);
+			: "__GCC_push_shmedia_regs_nofpu"), SFUNC_GOT, NULL);
       emit_insn (gen_shmedia_save_restore_regs_compact
 		 (GEN_INT (-SHMEDIA_REGS_STACK_ADJUST ())));
     }
@@ -6540,7 +6611,7 @@
       /* This must NOT go through the PLT, otherwise mach and macl
 	 may be clobbered.  */
       function_symbol (gen_rtx_REG (Pmode, R0_REG),
-		      "__GCC_shcompact_incoming_args", SFUNC_GOT);
+		      "__GCC_shcompact_incoming_args", SFUNC_GOT, NULL);
       emit_insn (gen_shcompact_incoming_args ());
     }
 }
@@ -6619,7 +6690,7 @@
       function_symbol (gen_rtx_REG (Pmode, R0_REG),
 		       (TARGET_FPU_ANY
 			? "__GCC_pop_shmedia_regs"
-			: "__GCC_pop_shmedia_regs_nofpu"), SFUNC_GOT);
+			: "__GCC_pop_shmedia_regs_nofpu"), SFUNC_GOT, NULL);
       /* This must NOT go through the PLT, otherwise mach and macl
 	 may be clobbered.  */
       emit_insn (gen_shmedia_save_restore_regs_compact
@@ -8818,9 +8889,12 @@
 	  || XINT (x, 1) == UNSPEC_GOTPLT
 	  || XINT (x, 1) == UNSPEC_GOTTPOFF
 	  || XINT (x, 1) == UNSPEC_DTPOFF
+	  || XINT (x, 1) == UNSPEC_TPOFF
 	  || XINT (x, 1) == UNSPEC_PLT
 	  || XINT (x, 1) == UNSPEC_SYMOFF
-	  || XINT (x, 1) == UNSPEC_PCREL_SYMOFF))
+	  || XINT (x, 1) == UNSPEC_PCREL_SYMOFF
+	  || XINT (x, 1) == UNSPEC_GOTFUNCDESC
+	  || XINT (x, 1) == UNSPEC_GOTOFFFUNCDESC))
     return 0;
 
   fmt = GET_RTX_FORMAT (GET_CODE (x));
@@ -8856,7 +8930,26 @@
       if (reg == 0)
 	reg = gen_reg_rtx (Pmode);
 
-      emit_insn (gen_symGOTOFF2reg (reg, orig));
+      if (TARGET_FDPIC
+	  && GET_CODE (orig) == SYMBOL_REF
+	  && SYMBOL_REF_FUNCTION_P (orig))
+	{
+	  /* Weak functions may be NULL which doesn't work with
+	     GOTOFFFUNCDESC because the runtime offset is not known.  */
+	  if (SYMBOL_REF_WEAK (orig))
+	    emit_insn (gen_symGOTFUNCDESC2reg (reg, orig));
+	  else
+	    emit_insn (gen_symGOTOFFFUNCDESC2reg (reg, orig));
+	}
+      else if (TARGET_FDPIC
+	       && (GET_CODE (orig) == LABEL_REF
+		   || (GET_CODE (orig) == SYMBOL_REF
+		       && SYMBOL_REF_DECL (orig)
+		       && TREE_READONLY (SYMBOL_REF_DECL (orig)))))
+	/* In FDPIC, GOTOFF can only be used for writable data.  */
+	emit_insn (gen_symGOT2reg (reg, orig));
+      else
+	emit_insn (gen_symGOTOFF2reg (reg, orig));
       return reg;
     }
   else if (GET_CODE (orig) == SYMBOL_REF)
@@ -8864,7 +8957,10 @@
       if (reg == 0)
 	reg = gen_reg_rtx (Pmode);
 
-      emit_insn (gen_symGOT2reg (reg, orig));
+      if (TARGET_FDPIC && SYMBOL_REF_FUNCTION_P (orig))
+	emit_insn (gen_symGOTFUNCDESC2reg (reg, orig));
+      else
+	emit_insn (gen_symGOT2reg (reg, orig));
       return reg;
     }
   return orig;
@@ -9814,7 +9910,7 @@
       if (!TARGET_INLINE_IC_INVALIDATE
 	  || (!(TARGET_SH4A_ARCH || TARGET_SH4_300) && TARGET_USERMODE))
 	emit_library_call (function_symbol (NULL, "__ic_invalidate",
-					    FUNCTION_ORDINARY),
+					    FUNCTION_ORDINARY, NULL),
 			   0, VOIDmode, 1, tramp, SImode);
       else
 	emit_insn (gen_ic_invalidate_line (tramp));
@@ -10585,10 +10681,18 @@
     sibcall = gen_sibcalli_thunk (funexp, const0_rtx);
   else
 #endif
-  if (TARGET_SH2 && flag_pic)
+  if (TARGET_SH2 && (flag_pic || TARGET_FDPIC))
     {
-      sibcall = gen_sibcall_pcrel (funexp, const0_rtx);
-      XEXP (XVECEXP (sibcall, 0, 2), 0) = scratch2;
+      if (TARGET_FDPIC)
+        {
+	  sibcall = gen_sibcall_pcrel_fdpic (funexp, const0_rtx);
+          XEXP (XVECEXP (sibcall, 0, 3), 0) = scratch2;
+        }
+      else
+        {
+	  sibcall = gen_sibcall_pcrel (funexp, const0_rtx);
+          XEXP (XVECEXP (sibcall, 0, 2), 0) = scratch2;
+        }
     }
   else
     {
@@ -10664,11 +10768,24 @@
   epilogue_completed = 0;
 }
 
+/* Return an RTX for the address of a function NAME of kind KIND,
+   placing the result in TARGET if not NULL.  LAB should be non-NULL
+   for SFUNC_STATIC, if FDPIC; it will be set to (const_int 0) if jsr
+   should be used, or a label_ref if bsrf should be used.  For FDPIC,
+   both SFUNC_GOT and SFUNC_STATIC will return the address of the
+   function itself, not a function descriptor, so they can only be
+   used with functions not using the FDPIC register that are known to
+   be called directory without a PLT entry.  */
+
 rtx
-function_symbol (rtx target, const char *name, enum sh_function_kind kind)
+function_symbol (rtx target, const char *name, enum sh_function_kind kind,
+		 rtx *lab)
 {
   rtx sym;
 
+  if (lab)
+    *lab = const0_rtx;
+
   /* If this is not an ordinary function, the name usually comes from a
      string literal or an sprintf buffer.  Make sure we use the same
      string consistently, so that cse will be able to unify address loads.  */
@@ -10676,7 +10793,7 @@
     name = IDENTIFIER_POINTER (get_identifier (name));
   sym = gen_rtx_SYMBOL_REF (Pmode, name);
   SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_FUNCTION;
-  if (flag_pic)
+  if (flag_pic || TARGET_FDPIC)
     switch (kind)
       {
       case FUNCTION_ORDINARY:
@@ -10691,14 +10808,27 @@
 	}
       case SFUNC_STATIC:
 	{
-	  /* ??? To allow cse to work, we use GOTOFF relocations.
-	     we could add combiner patterns to transform this into
-	     straight pc-relative calls with sym2PIC / bsrf when
-	     label load and function call are still 1:1 and in the
-	     same basic block during combine.  */
 	  rtx reg = target ? target : gen_reg_rtx (Pmode);
 
-	  emit_insn (gen_symGOTOFF2reg (reg, sym));
+	  if (TARGET_FDPIC)
+	    {
+	      /* We use PC-relative calls, since GOTOFF can only refer
+		 to writable data.  This works along with
+		 sh_sfunc_call.  */
+	      gcc_assert (lab != NULL);
+	      *lab = PATTERN (gen_call_site ());
+	      emit_insn (gen_sym_label2reg (reg, sym, *lab));
+	    }
+	  else
+	    {
+	      /* ??? To allow cse to work, we use GOTOFF relocations.
+		 we could add combiner patterns to transform this into
+		 straight pc-relative calls with sym2PIC / bsrf when
+		 label load and function call are still 1:1 and in the
+		 same basic block during combine.  */
+	      emit_insn (gen_symGOTOFF2reg (reg, sym));
+	    }
+
 	  sym = reg;
 	  break;
 	}
@@ -11338,4 +11468,61 @@
 
 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
 
+bool
+sh_illegitimate_symbolic_constant_p (rtx x)
+{
+  rtx base, offset;
+
+  if (TARGET_FDPIC && !LEGITIMATE_PIC_OPERAND_P (x))
+    return true;
+
+  if (SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+    {
+      split_const (x, &base, &offset);
+      if (GET_CODE (base) == SYMBOL_REF
+	  && !offset_within_block_p (base, INTVAL (offset)))
+	return true;
+    }
+  return false;
+}
+
+/* Emit insns to load the function address from FUNCDESC (an FDPIC
+   function descriptor) into r1 and the GOT address into r12,
+   returning an rtx for r1.  */
+
+rtx
+sh_load_function_descriptor (rtx funcdesc)
+{
+  rtx r1 = gen_rtx_REG (Pmode, R1_REG);
+  rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+  rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
+  rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (funcdesc, 4));
+
+  emit_move_insn (r1, fnaddr);
+  /* The ABI requires the entry point address to be loaded first, so
+     prevent the load from being moved after that of the GOT
+     address.  */
+  emit_insn (gen_blockage ());
+  emit_move_insn (pic_reg, gotaddr);
+  return r1;
+}
+
+/* Return an rtx holding the initial value of the FDPIC register (the
+   FDPIC pointer passed in from the caller).  */
+
+rtx
+sh_our_fdpic_reg (void)
+{
+  return get_hard_reg_initial_val (Pmode, PIC_REG);
+}
+
+/* Relocatable data for FDPIC binaries is not permitted in read-only
+   segments.  */
+
+static int
+sh_reloc_rw_mask (void)
+{
+  return (flag_pic || TARGET_FDPIC) ? 3 : 0;
+}
+
 #include "gt-sh.h"
diff -Naur a/src/gcc/config/sh/sh.h b/src/gcc/config/sh/sh.h
--- a/src/gcc/config/sh/sh.h	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/sh.h	2010-03-30 10:39:22.000000000 +0300
@@ -91,6 +91,11 @@
     builtin_define ("__SH_FPU_DOUBLE__"); \
   if (TARGET_HITACHI) \
     builtin_define ("__HITACHI__"); \
+  if (TARGET_FDPIC) \
+    { \
+      builtin_define ("__SH_FDPIC__"); \
+      builtin_define ("__FDPIC__"); \
+    } \
   builtin_define (TARGET_LITTLE_ENDIAN \
 		  ? "__LITTLE_ENDIAN__" : "__BIG_ENDIAN__"); \
 } while (0)
@@ -123,6 +128,12 @@
       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;				\
       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;			\
     }									\
+  if (TARGET_FDPIC)							\
+    {									\
+      fixed_regs[PIC_REG] = 1;						\
+      call_used_regs[PIC_REG] = 1;					\
+      call_really_used_regs[PIC_REG] = 1;				\
+    }									\
   /* Renesas saves and restores mac registers on call.  */		\
   if (TARGET_HITACHI && ! TARGET_NOMACSAVE)				\
     {									\
@@ -458,7 +469,10 @@
 #define SH_DIV_STR_FOR_SIZE "call"
 #endif
 
-#define DRIVER_SELF_SPECS "%{m2a:%{ml:%eSH2a does not support little-endian}}"
+#define DRIVER_SELF_SPECS SUBTARGET_DRIVER_SELF_SPECS \
+  "%{m2a:%{ml:%eSH2a does not support little-endian}}"
+#define SUBTARGET_DRIVER_SELF_SPECS
+
 #define OPTIMIZATION_OPTIONS(LEVEL,SIZE)				\
 do {									\
   if (LEVEL)								\
@@ -684,6 +698,10 @@
     sh_branch_cost							\
       = TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1;	\
 									\
+  if (TARGET_FDPIC							\
+      && (TARGET_SHMEDIA || TARGET_SHCOMPACT || !TARGET_SH2))		\
+    sorry ("non-SH2 FDPIC");						\
+									\
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)		\
     if (! VALID_REGISTER_P (regno))					\
       sh_register_names[regno][0] = '\0';				\
@@ -703,7 +721,7 @@
       flag_omit_frame_pointer = 0;					\
    }									\
 									\
-  if ((flag_pic && ! TARGET_PREFERGOT)					\
+  if (((flag_pic || TARGET_FDPIC) && ! TARGET_PREFERGOT)		\
       || (TARGET_SHMEDIA && !TARGET_PT_FIXED))				\
     flag_no_function_cse = 1;						\
 									\
@@ -1263,6 +1281,14 @@
    code access to data items.  */
 #define PIC_OFFSET_TABLE_REGNUM	(flag_pic ? PIC_REG : INVALID_REGNUM)
 
+/* For FDPIC, the FDPIC register is call-clobbered (otherwise PLT
+   entries would need to handle saving and restoring it).  */
+#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED TARGET_FDPIC
+
+/* An rtx holding the initial value of the FDPIC register (the FDPIC
+   pointer passed in from the caller).  */
+#define OUR_FDPIC_REG		sh_our_fdpic_reg ()
+
 #define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
 
 /* Value should be nonzero if functions must have frame pointers.
@@ -2175,6 +2201,10 @@
       || GENERAL_REGISTER_P ((unsigned) reg_renumber[(REGNO)])) \
    : (REGNO) == R0_REG || (unsigned) reg_renumber[(REGNO)] == R0_REG)
 
+/* True if SYMBOL + OFFSET constants must refer to something within
+   SYMBOL's section.  */
+#define SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 0
+
 /* Maximum number of registers that can appear in a valid memory
    address.  */
 
@@ -2188,7 +2218,7 @@
 /* can_store_by_pieces constructs VOIDmode CONST_DOUBLEs.  */
 
 #define LEGITIMATE_CONSTANT_P(X) \
-  (TARGET_SHMEDIA							\
+  ((TARGET_SHMEDIA							\
    ? ((GET_MODE (X) != DFmode						\
        && GET_MODE_CLASS (GET_MODE (X)) != MODE_VECTOR_FLOAT)		\
       || (X) == CONST0_RTX (GET_MODE (X))				\
@@ -2196,7 +2226,8 @@
       || TARGET_SHMEDIA64)						\
    : (GET_CODE (X) != CONST_DOUBLE					\
       || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode		\
-      || GET_MODE (X) == DImode || GET_MODE (X) == VOIDmode))
+      || GET_MODE (X) == DImode || GET_MODE (X) == VOIDmode))		\
+   && !sh_illegitimate_symbolic_constant_p (X))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -3135,6 +3166,14 @@
 	    output_addr_const (STREAM, XVECEXP (X, 0, 1));		\
 	    fputs ("-.)", STREAM);					\
 	    break;							\
+	  case UNSPEC_GOTFUNCDESC:					\
+	    output_addr_const ((STREAM), XVECEXP ((X), 0, 0));		\
+	    fputs ("@GOTFUNCDESC", (STREAM));				\
+	    break;							\
+	  case UNSPEC_GOTOFFFUNCDESC:					\
+	    output_addr_const ((STREAM), XVECEXP ((X), 0, 0));		\
+	    fputs ("@GOTOFFFUNCDESC", (STREAM));			\
+	    break;							\
 	  default:							\
 	    goto FAIL;							\
 	  }								\
diff -Naur a/src/gcc/config/sh/sh.md b/src/gcc/config/sh/sh.md
--- a/src/gcc/config/sh/sh.md	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/sh.md	2010-04-10 10:19:15.000000000 +0300
@@ -164,6 +164,9 @@
   ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
   (UNSPEC_PCREL_SYMOFF	46)
 
+  (UNSPEC_GOTFUNCDESC	50)
+  (UNSPEC_GOTOFFFUNCDESC	51)
+
   ;; These are used with unspec_volatile.
   (UNSPECV_BLOCKAGE	0)
   (UNSPECV_ALIGN	1)
@@ -734,7 +737,7 @@
   [(set (pc)
 	(if_then_else (match_operator 0 "comparison_operator"
 			[(match_operand:DI 1 "arith_operand" "r,r")
-			 (match_operand:DI 2 "arith_operand" "rN,i")])
+			 (match_operand:DI 2 "arith_operand" "rN,I08")])
 		      (label_ref (match_operand 3 "" ""))
 		      (pc)))
    (clobber (match_scratch:SI 4 "=X,&r"))
@@ -1751,14 +1754,17 @@
 ;; If we let reload allocate r0, then this problem can never happen.
 
 (define_insn "udivsi3_i1"
-  [(set (match_operand:SI 0 "register_operand" "=z")
+  [(set (match_operand:SI 0 "register_operand" "=z,z")
 	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
    (clobber (reg:SI R4_REG))
-   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
+   (use (match_operand 2 "" "Z,Ccl"))]
   "TARGET_SH1 && ! TARGET_SH4"
-  "jsr	@%1%#"
+  "@
+   jsr	@%1%#
+   bsrf	%1\\n%O2:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
@@ -1808,7 +1814,7 @@
 }")
 
 (define_insn "udivsi3_i4"
-  [(set (match_operand:SI 0 "register_operand" "=y")
+  [(set (match_operand:SI 0 "register_operand" "=y,y")
 	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
@@ -1820,15 +1826,18 @@
    (clobber (reg:SI R4_REG))
    (clobber (reg:SI R5_REG))
    (use (reg:PSI FPSCR_REG))
-   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
+   (use (match_operand 2 "" "Z,Ccl"))]
   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
-  "jsr	@%1%#"
+  "@
+   jsr	@%1%#
+   bsrf	%1\\n%O2:%#"
   [(set_attr "type" "sfunc")
    (set_attr "fp_mode" "double")
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "udivsi3_i4_single"
-  [(set (match_operand:SI 0 "register_operand" "=y")
+  [(set (match_operand:SI 0 "register_operand" "=y,y")
 	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
@@ -1839,9 +1848,12 @@
    (clobber (reg:SI R1_REG))
    (clobber (reg:SI R4_REG))
    (clobber (reg:SI R5_REG))
-   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
+   (use (match_operand 2 "" "Z,Ccl"))]
   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
-  "jsr	@%1%#"
+  "@
+   jsr	@%1%#
+   bsrf	%1\\n%O2:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
@@ -1895,16 +1907,17 @@
 	  emit_move_insn (operands[0], operands[2]);
 	  DONE;
 	}
-      function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
+      function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT, NULL);
       last = gen_udivsi3_i4_int (operands[0], operands[3]);
     }
   else if (TARGET_DIVIDE_CALL_FP)
     {
-      function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
+      rtx lab;
+      function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC, &lab);
       if (TARGET_FPU_SINGLE)
-	last = gen_udivsi3_i4_single (operands[0], operands[3]);
+	last = gen_udivsi3_i4_single (operands[0], operands[3], lab);
       else
-	last = gen_udivsi3_i4 (operands[0], operands[3]);
+	last = gen_udivsi3_i4 (operands[0], operands[3], lab);
     }
   else if (TARGET_SHMEDIA_FPU)
     {
@@ -1924,19 +1937,20 @@
     {
       function_symbol (operands[3],
 		       TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
-		       SFUNC_STATIC);
+		       SFUNC_STATIC, NULL);
 
       if (TARGET_SHMEDIA)
 	last = gen_udivsi3_i1_media (operands[0], operands[3]);
       else if (TARGET_FPU_ANY)
-	last = gen_udivsi3_i4_single (operands[0], operands[3]);
+	last = gen_udivsi3_i4_single (operands[0], operands[3], const0_rtx);
       else
-	last = gen_udivsi3_i1 (operands[0], operands[3]);
+	last = gen_udivsi3_i1 (operands[0], operands[3], const0_rtx);
     }
   else
     {
-      function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
-      last = gen_udivsi3_i1 (operands[0], operands[3]);
+      rtx lab;
+      function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC, &lab);
+      last = gen_udivsi3_i1 (operands[0], operands[3], lab);
     }
   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
@@ -2065,7 +2079,7 @@
       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
       break;
     }
-  sym = function_symbol (NULL, name, kind);
+  sym = function_symbol (NULL, name, kind, NULL);
   emit_insn (gen_divsi3_media_2 (operands[0], sym));
   DONE;
 }"
@@ -2086,29 +2100,35 @@
 }")
 
 (define_insn "divsi3_i4"
-  [(set (match_operand:SI 0 "register_operand" "=y")
+  [(set (match_operand:SI 0 "register_operand" "=y,y")
 	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:SI PR_REG))
    (clobber (reg:DF DR0_REG))
    (clobber (reg:DF DR2_REG))
    (use (reg:PSI FPSCR_REG))
-   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
+   (use (match_operand 2 "" "Z,Ccl"))]
   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
-  "jsr	@%1%#"
+  "@
+   jsr	@%1%#
+   bsrf	%1\\n%O2:%#"
   [(set_attr "type" "sfunc")
    (set_attr "fp_mode" "double")
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "divsi3_i4_single"
-  [(set (match_operand:SI 0 "register_operand" "=y")
+  [(set (match_operand:SI 0 "register_operand" "=y,y")
 	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:SI PR_REG))
    (clobber (reg:DF DR0_REG))
    (clobber (reg:DF DR2_REG))
    (clobber (reg:SI R2_REG))
-   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
+   (use (match_operand 2 "" "Z,Ccl"))]
   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
-  "jsr	@%1%#"
+  "@
+   jsr	@%1%#
+   bsrf	%1\\n%O2:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
@@ -2148,16 +2168,17 @@
   /* Emit the move of the address to a pseudo outside of the libcall.  */
   if (TARGET_DIVIDE_CALL_TABLE)
     {
-      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
+      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT, NULL);
       last = gen_divsi3_i4_int (operands[0], operands[3]);
     }
   else if (TARGET_DIVIDE_CALL_FP)
     {
-      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
+      rtx lab;
+      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC, &lab);
       if (TARGET_FPU_SINGLE)
-	last = gen_divsi3_i4_single (operands[0], operands[3]);
+	last = gen_divsi3_i4_single (operands[0], operands[3], lab);
       else
-	last = gen_divsi3_i4 (operands[0], operands[3]);
+	last = gen_divsi3_i4 (operands[0], operands[3], lab);
     }
   else if (TARGET_SH2A)
     {
@@ -2262,23 +2283,23 @@
 	  emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
 	}
       if (TARGET_FPU_ANY && TARGET_SH1)
-	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
+	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC, NULL);
       else if (TARGET_DIVIDE_CALL2)
-	function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
+	function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC, NULL);
       else
-	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
+	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT, NULL);
 
       if (TARGET_SHMEDIA)
 	last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
 		(operands[0], operands[3]));
       else if (TARGET_FPU_ANY)
-	last = gen_divsi3_i4_single (operands[0], operands[3]);
+	last = gen_divsi3_i4_single (operands[0], operands[3], const0_rtx);
       else
 	last = gen_divsi3_i1 (operands[0], operands[3]);
     }
   else
     {
-      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
+      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT, NULL);
       last = gen_divsi3_i1 (operands[0], operands[3]);
     }
   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
@@ -2870,7 +2891,7 @@
     {
       /* The address must be set outside the libcall,
 	 since it goes into a pseudo.  */
-      rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
+      rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC, NULL);
       rtx addr = force_reg (SImode, sym);
       rtx insns = gen_mulsi3_call (operands[0], operands[1],
 				   operands[2], addr);
@@ -3841,12 +3862,15 @@
 (define_insn "ashrsi3_n"
   [(set (reg:SI R4_REG)
 	(ashiftrt:SI (reg:SI R4_REG)
-		     (match_operand:SI 0 "const_int_operand" "i")))
+		     (match_operand:SI 0 "const_int_operand" "i,i")))
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
-   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
+   (use (match_operand 2 "" "Z,Ccl"))]
   "TARGET_SH1"
-  "jsr	@%1%#"
+  "@
+   jsr	@%1%#
+   bsrf	%1\\n%O2:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
@@ -5265,7 +5289,8 @@
     }
   else if (TARGET_SHCOMPACT)
     {
-      operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
+      operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC,
+				     NULL);
       operands[1] = force_reg (Pmode, operands[1]);
       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
       DONE;
@@ -5334,7 +5359,7 @@
 
   tramp = force_reg (Pmode, operands[0]);
   sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
-					    SFUNC_STATIC));
+					    SFUNC_STATIC, NULL));
   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
 
@@ -7524,7 +7549,29 @@
 	 (match_operand 1 "" ""))
    (use (reg:PSI FPSCR_REG))
    (clobber (reg:SI PR_REG))]
-  "TARGET_SH1"
+  "TARGET_SH1 && !TARGET_FDPIC"
+  "*
+   {
+     if (TARGET_SH2A && (dbr_sequence_length () == 0))
+	return \"jsr/n\\t@%0\";
+     else
+	return \"jsr\\t@%0%#\";
+   }"
+
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")
+   (set_attr "fp_set" "unknown")])
+
+(define_insn "calli_fdpic"
+  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
+	 (match_operand 1 "" ""))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SH1 && TARGET_FDPIC"
   "*
    {
      if (TARGET_SH2A && (dbr_sequence_length () == 0))
@@ -7659,7 +7706,29 @@
 	      (match_operand 2 "" "")))
    (use (reg:PSI FPSCR_REG))
    (clobber (reg:SI PR_REG))]
-  "TARGET_SH1"
+  "TARGET_SH1 && !TARGET_FDPIC"
+  "*
+   {
+     if (TARGET_SH2A && (dbr_sequence_length () == 0))
+	return \"jsr/n\\t@%1\";
+     else
+	return \"jsr\\t@%1%#\";
+   }"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")
+   (set_attr "fp_set" "unknown")])
+
+(define_insn "call_valuei_fdpic"
+  [(set (match_operand 0 "" "=rf")
+	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+	      (match_operand 2 "" "")))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SH1 && TARGET_FDPIC"
   "*
    {
      if (TARGET_SH2A && (dbr_sequence_length () == 0))
@@ -7801,6 +7870,12 @@
   ""
   "
 {
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+    }
+
   if (TARGET_SHMEDIA)
     {
       operands[0] = shmedia_prepare_call_address (operands[0], 0);
@@ -7837,7 +7912,7 @@
 
       operands[0]
 	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
-			   SFUNC_GOT);
+			   SFUNC_GOT, NULL);
       operands[0] = force_reg (SImode, operands[0]);
 
       emit_move_insn (r0, func);
@@ -7861,7 +7936,7 @@
       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
       XEXP (operands[0], 0) = reg;
     }
-  if (!flag_pic && TARGET_SH2A
+  if (!flag_pic && !TARGET_FDPIC && TARGET_SH2A
       && GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
     {
@@ -7872,7 +7947,7 @@
 	  DONE;
 	}
     }
-  if (flag_pic && TARGET_SH2
+  if ((flag_pic || TARGET_FDPIC) && TARGET_SH2
       && GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
     {
@@ -7885,7 +7960,13 @@
     operands[1] = operands[2];
   }
 
-  emit_call_insn (gen_calli (operands[0], operands[1]));
+  if (TARGET_FDPIC)
+    {
+      operands[0] = sh_load_function_descriptor (operands[0]);
+      emit_call_insn (gen_calli_fdpic (operands[0], operands[1]));
+    }
+  else
+    emit_call_insn (gen_calli (operands[0], operands[1]));
   DONE;
 }")
 
@@ -7966,7 +8047,7 @@
   emit_insn (gen_force_mode_for_call ());
 
   operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
-				 SFUNC_GOT);
+				 SFUNC_GOT, NULL);
   operands[0] = force_reg (SImode, operands[0]);
 
   emit_move_insn (r0, func);
@@ -7992,6 +8073,12 @@
   ""
   "
 {
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+    }
+
   if (TARGET_SHMEDIA)
     {
       operands[1] = shmedia_prepare_call_address (operands[1], 0);
@@ -8029,7 +8116,7 @@
 
       operands[1]
 	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
-			   SFUNC_GOT);
+			   SFUNC_GOT, NULL);
       operands[1] = force_reg (SImode, operands[1]);
 
       emit_move_insn (r0, func);
@@ -8055,7 +8142,7 @@
       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
       XEXP (operands[1], 0) = reg;
     }
-  if (!flag_pic && TARGET_SH2A
+  if (!flag_pic && !TARGET_FDPIC && TARGET_SH2A
       && GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
     {
@@ -8066,7 +8153,7 @@
 	  DONE;
 	}
     }
-  if (flag_pic && TARGET_SH2
+  if ((flag_pic || TARGET_FDPIC) && TARGET_SH2
       && GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
     {
@@ -8077,7 +8164,14 @@
   else
     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
 
-  emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
+  if (TARGET_FDPIC)
+    {
+      operands[1] = sh_load_function_descriptor (operands[1]);
+      emit_call_insn (gen_call_valuei_fdpic (operands[0], operands[1],
+					     operands[2]));
+    }
+  else
+    emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
   DONE;
 }")
 
@@ -8086,7 +8180,21 @@
 	 (match_operand 1 "" ""))
    (use (reg:PSI FPSCR_REG))
    (return)]
-  "TARGET_SH1"
+  "TARGET_SH1 && !TARGET_FDPIC"
+  "jmp	@%0%#"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcalli_fdpic"
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
+	 (match_operand 1 "" ""))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (return)]
+  "TARGET_SH1 && TARGET_FDPIC"
   "jmp	@%0%#"
   [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
@@ -8100,7 +8208,22 @@
    (use (match_operand 2 "" ""))
    (use (reg:PSI FPSCR_REG))
    (return)]
-  "TARGET_SH2"
+  "TARGET_SH2 && !TARGET_FDPIC"
+  "braf	%0\\n%O2:%#"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcalli_pcrel_fdpic"
+  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
+	 (match_operand 1 "" ""))
+   (use (match_operand 2 "" ""))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (return)]
+  "TARGET_SH2 && TARGET_FDPIC"
   "braf	%0\\n%O2:%#"
   [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
@@ -8130,7 +8253,7 @@
    (use (reg:PSI FPSCR_REG))
    (clobber (match_scratch:SI 2 "=k"))
    (return)]
-  "TARGET_SH2"
+  "TARGET_SH2 && !TARGET_FDPIC"
   "#"
   "reload_completed"
   [(const_int 0)]
@@ -8151,6 +8274,34 @@
 		      (const_string "single") (const_string "double")))
    (set_attr "type" "jump_ind")])
 
+(define_insn_and_split "sibcall_pcrel_fdpic"
+  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
+	 (match_operand 1 "" ""))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (clobber (match_scratch:SI 2 "=k"))
+   (return)]
+  "TARGET_SH2 && TARGET_FDPIC"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx lab = PATTERN (gen_call_site ());
+  rtx call_insn;
+
+  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
+  call_insn = emit_call_insn (gen_sibcalli_pcrel_fdpic (operands[2], operands[1],
+						  copy_rtx (lab)));
+  SIBLING_CALL_P (call_insn) = 1;
+  DONE;
+}"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
 (define_insn "sibcall_compact"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
 	 (match_operand 1 "" ""))
@@ -8189,6 +8340,12 @@
   ""
   "
 {
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+    }
+
   if (TARGET_SHMEDIA)
     {
       operands[0] = shmedia_prepare_call_address (operands[0], 1);
@@ -8235,7 +8392,7 @@
 
       operands[0]
 	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
-			   SFUNC_GOT);
+			   SFUNC_GOT, NULL);
       operands[0] = force_reg (SImode, operands[0]);
 
       /* We don't need a return trampoline, since the callee will
@@ -8261,7 +8418,7 @@
       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
       XEXP (operands[0], 0) = reg;
     }
-  if (flag_pic && TARGET_SH2
+  if ((flag_pic || TARGET_FDPIC) && TARGET_SH2
       && GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
       /* The PLT needs the PIC register, but the epilogue would have
@@ -8269,13 +8426,24 @@
 	 static functions.  */
       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
     {
-      emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
+      if (TARGET_FDPIC)
+        emit_call_insn (gen_sibcall_pcrel_fdpic (XEXP (operands[0], 0),
+       	                                         operands[1]));
+      else
+        emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0),
+                                           operands[1]));
       DONE;
     }
   else
     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
 
-  emit_call_insn (gen_sibcalli (operands[0], operands[1]));
+  if (TARGET_FDPIC)
+    {
+      operands[0] = sh_load_function_descriptor (operands[0]);
+      emit_call_insn (gen_sibcalli_fdpic (operands[0], operands[1]));
+    }
+  else
+    emit_call_insn (gen_sibcalli (operands[0], operands[1]));
   DONE;
 }")
 
@@ -8285,7 +8453,22 @@
 	      (match_operand 2 "" "")))
    (use (reg:PSI FPSCR_REG))
    (return)]
-  "TARGET_SH1"
+  "TARGET_SH1 && !TARGET_FDPIC"
+  "jmp	@%1%#"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcall_valuei_fdpic"
+  [(set (match_operand 0 "" "=rf")
+	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
+	      (match_operand 2 "" "")))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (return)]
+  "TARGET_SH1 && TARGET_FDPIC"
   "jmp	@%1%#"
   [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
@@ -8300,7 +8483,23 @@
    (use (match_operand 3 "" ""))
    (use (reg:PSI FPSCR_REG))
    (return)]
-  "TARGET_SH2"
+  "TARGET_SH2 && !TARGET_FDPIC"
+  "braf	%1\\n%O3:%#"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcall_valuei_pcrel_fdpic"
+  [(set (match_operand 0 "" "=rf")
+	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
+	      (match_operand 2 "" "")))
+   (use (match_operand 3 "" ""))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:PSI PIC_REG))
+   (return)]
+  "TARGET_SH2 && TARGET_FDPIC"
   "braf	%1\\n%O3:%#"
   [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
@@ -8315,7 +8514,7 @@
    (use (reg:PSI FPSCR_REG))
    (clobber (match_scratch:SI 3 "=k"))
    (return)]
-  "TARGET_SH2"
+  "TARGET_SH2 && !TARGET_FDPIC"
   "#"
   "reload_completed"
   [(const_int 0)]
@@ -8329,6 +8528,39 @@
 							operands[3],
 							operands[2],
 							copy_rtx (lab)));
+							  
+  SIBLING_CALL_P (call_insn) = 1;
+  DONE;
+}"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+	(if_then_else (eq_attr "fpu_single" "yes")
+		      (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn_and_split "sibcall_value_pcrel_fdpic"
+  [(set (match_operand 0 "" "=rf")
+	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
+	      (match_operand 2 "" "")))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:PSI PIC_REG))
+   (clobber (match_scratch:SI 3 "=k"))
+   (return)]
+  "TARGET_SH2 && TARGET_FDPIC"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx lab = PATTERN (gen_call_site ());
+  rtx call_insn;
+
+  emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
+  call_insn = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0],
+							      operands[3],
+							      operands[2],
+							      copy_rtx (lab)));
+							  
   SIBLING_CALL_P (call_insn) = 1;
   DONE;
 }"
@@ -8379,6 +8611,12 @@
   ""
   "
 {
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+    }
+
   if (TARGET_SHMEDIA)
     {
       operands[1] = shmedia_prepare_call_address (operands[1], 1);
@@ -8426,7 +8664,7 @@
 
       operands[1]
 	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
-			   SFUNC_GOT);
+			   SFUNC_GOT, NULL);
       operands[1] = force_reg (SImode, operands[1]);
 
       /* We don't need a return trampoline, since the callee will
@@ -8453,7 +8691,7 @@
       emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
       XEXP (operands[1], 0) = reg;
     }
-  if (flag_pic && TARGET_SH2
+  if ((flag_pic || TARGET_FDPIC) && TARGET_SH2
       && GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
       /* The PLT needs the PIC register, but the epilogue would have
@@ -8461,15 +8699,28 @@
 	 static functions.  */
       && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
     {
-      emit_call_insn (gen_sibcall_value_pcrel (operands[0],
-					       XEXP (operands[1], 0),
-					       operands[2]));
+      if (TARGET_FDPIC)
+	emit_call_insn (gen_sibcall_value_pcrel_fdpic (operands[0],
+						       XEXP (operands[1], 0),
+						       operands[2]));
+      else
+	emit_call_insn (gen_sibcall_value_pcrel (operands[0],
+						 XEXP (operands[1], 0),
+						 operands[2]));
       DONE;
     }
   else
     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
 
-  emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
+  if (TARGET_FDPIC)
+    {
+      operands[1] = sh_load_function_descriptor (operands[1]);
+      emit_call_insn (gen_sibcall_valuei_fdpic (operands[0], operands[1],
+						operands[2]));
+    }
+  else
+    emit_call_insn (gen_sibcall_valuei (operands[0], operands[1],
+					operands[2]));
   DONE;
 }")
 
@@ -8554,7 +8805,7 @@
   emit_insn (gen_force_mode_for_call ());
 
   operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
-				 SFUNC_GOT);
+				 SFUNC_GOT, NULL);
   operands[1] = force_reg (SImode, operands[1]);
 
   emit_move_insn (r0, func);
@@ -8739,6 +8990,13 @@
       DONE;
     }
 
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+      DONE;
+    }
+
   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
 
@@ -8853,6 +9111,12 @@
 {
   rtx insn, mem;
 
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+    }
+
   operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
   operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
 
@@ -8926,6 +9190,27 @@
   DONE;
 }")
 
+(define_expand "sym2GOTFUNCDESC"
+  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTFUNCDESC))]
+  "TARGET_FDPIC"
+  "")
+
+(define_expand "symGOTFUNCDESC2reg"
+  [(match_operand 0 "" "") (match_operand 1 "" "")]
+  "TARGET_FDPIC"
+  "
+{
+  rtx gotsym, insn;
+
+  gotsym = gen_sym2GOTFUNCDESC (operands[1]);
+  PUT_MODE (gotsym, Pmode);
+  insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
+
+  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
+
+  DONE;
+}")
+
 (define_expand "symGOTPLT2reg"
   [(match_operand 0 "" "") (match_operand 1 "" "")]
   ""
@@ -8954,6 +9239,12 @@
 	   ? operands[0]
 	   : gen_reg_rtx (GET_MODE (operands[0])));
 
+  if (TARGET_FDPIC)
+    {
+      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+      emit_move_insn (pic_reg, OUR_FDPIC_REG);
+    }
+
   gotoffsym = gen_sym2GOTOFF (operands[1]);
   PUT_MODE (gotoffsym, Pmode);
   emit_move_insn (t, gotoffsym);
@@ -8966,6 +9257,33 @@
   DONE;
 }")
 
+(define_expand "sym2GOTOFFFUNCDESC"
+  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFFFUNCDESC))]
+  "TARGET_FDPIC"
+  "")
+
+(define_expand "symGOTOFFFUNCDESC2reg"
+  [(match_operand 0 "" "") (match_operand 1 "" "")]
+  "TARGET_FDPIC"
+  "
+{
+  rtx gotoffsym;
+  rtx t = (!can_create_pseudo_p ()
+	   ? operands[0]
+	   : gen_reg_rtx (GET_MODE (operands[0])));
+
+  rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
+  emit_move_insn (pic_reg, OUR_FDPIC_REG);
+
+  gotoffsym = gen_sym2GOTOFFFUNCDESC (operands[1]);
+  PUT_MODE (gotoffsym, Pmode);
+  emit_move_insn (t, gotoffsym);
+  emit_move_insn (operands[0],
+		  gen_rtx_PLUS (Pmode, t,
+				gen_rtx_REG (Pmode, PIC_REG)));
+  DONE;
+}")
+
 (define_expand "symPLT_label2reg"
   [(set (match_operand:SI 0 "" "")
 	(const:SI
@@ -9440,7 +9758,8 @@
 {
   rtx reg = gen_rtx_REG (Pmode, R0_REG);
 
-  function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
+  function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC,
+		   NULL);
   emit_jump_insn (gen_shcompact_return_tramp_i ());
   DONE;
 }")
@@ -9611,7 +9930,7 @@
 ;; complements the T bit and stores the result in a register
 (define_insn "movrt"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-        (if_then_else (eq:SI (reg:SI T_REG) (const_int 0))
+        (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
         (const_int 1)
         (const_int 0)))]
   "TARGET_SH2A"
@@ -10416,18 +10735,22 @@
 (define_insn "block_move_real"
   [(parallel [(set (mem:BLK (reg:SI R4_REG))
 		   (mem:BLK (reg:SI R5_REG)))
-	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
+	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+	      (use (match_operand 1 "" "Z,Ccl"))
 	      (clobber (reg:SI PR_REG))
 	      (clobber (reg:SI R0_REG))])]
   "TARGET_SH1 && ! TARGET_HARD_SH4"
-  "jsr	@%0%#"
+  "@
+   jsr	@%0%#
+   bsrf	%0\\n%O1:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "block_lump_real"
   [(parallel [(set (mem:BLK (reg:SI R4_REG))
 		   (mem:BLK (reg:SI R5_REG)))
-	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
+	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+	      (use (match_operand 1 "" "Z,Ccl"))
 	      (use (reg:SI R6_REG))
 	      (clobber (reg:SI PR_REG))
 	      (clobber (reg:SI T_REG))
@@ -10436,27 +10759,33 @@
 	      (clobber (reg:SI R6_REG))
 	      (clobber (reg:SI R0_REG))])]
   "TARGET_SH1 && ! TARGET_HARD_SH4"
-  "jsr	@%0%#"
+  "@
+   jsr	@%0%#
+   bsrf	%0\\n%O1:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "block_move_real_i4"
   [(parallel [(set (mem:BLK (reg:SI R4_REG))
 		   (mem:BLK (reg:SI R5_REG)))
-	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
+	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+	      (use (match_operand 1 "" "Z,Ccl"))
 	      (clobber (reg:SI PR_REG))
 	      (clobber (reg:SI R0_REG))
 	      (clobber (reg:SI R1_REG))
 	      (clobber (reg:SI R2_REG))])]
   "TARGET_HARD_SH4"
-  "jsr	@%0%#"
+  "@
+   jsr	@%0%#
+   bsrf	%0\\n%O1:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "block_lump_real_i4"
   [(parallel [(set (mem:BLK (reg:SI R4_REG))
 		   (mem:BLK (reg:SI R5_REG)))
-	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
+	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+	      (use (match_operand 1 "" "Z,Ccl"))
 	      (use (reg:SI R6_REG))
 	      (clobber (reg:SI PR_REG))
 	      (clobber (reg:SI T_REG))
@@ -10468,7 +10797,9 @@
 	      (clobber (reg:SI R2_REG))
 	      (clobber (reg:SI R3_REG))])]
   "TARGET_HARD_SH4"
-  "jsr	@%0%#"
+  "@
+   jsr	@%0%#
+   bsrf	%0\\n%O1:%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
diff -Naur a/src/gcc/config/sh/sh.opt b/src/gcc/config/sh/sh.opt
--- a/src/gcc/config/sh/sh.opt	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/sh.opt	2010-03-30 10:39:22.000000000 +0300
@@ -252,6 +252,10 @@
 Target RejectNegative Joined Var(sh_fixed_range_str)
 Specify range of registers to make fixed
 
+mfdpic
+Target Report Mask(FDPIC)
+Generate ELF FDPIC code
+
 mfmovd
 Target RejectNegative Mask(FMOVD) Undocumented
 
diff -Naur a/src/gcc/config/sh/sh-protos.h b/src/gcc/config/sh/sh-protos.h
--- a/src/gcc/config/sh/sh-protos.h	2009-10-12 21:20:53.000000000 +0300
+++ b/src/gcc/config/sh/sh-protos.h	2010-03-30 10:39:22.000000000 +0300
@@ -152,7 +152,7 @@
 extern void sh_pr_interrupt (struct cpp_reader *);
 extern void sh_pr_trapa (struct cpp_reader *);
 extern void sh_pr_nosave_low_regs (struct cpp_reader *);
-extern rtx function_symbol (rtx, const char *, enum sh_function_kind);
+extern rtx function_symbol (rtx, const char *, enum sh_function_kind, rtx *);
 extern rtx sh_get_pr_initial_val (void);
 
 extern rtx sh_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
@@ -175,6 +175,9 @@
 extern int sh2a_is_function_vector_call (rtx);
 extern void sh_fix_range (const char *);
 extern bool sh_hard_regno_mode_ok (unsigned int, enum machine_mode);
+extern bool sh_illegitimate_symbolic_constant_p (rtx);
+extern rtx sh_load_function_descriptor (rtx);
+extern rtx sh_our_fdpic_reg (void);
 #endif /* ! GCC_SH_PROTOS_H */
 
 #ifdef SYMBIAN
diff -Naur a/src/gcc/config/sh/t-uclinux b/src/gcc/config/sh/t-uclinux
--- a/src/gcc/config/sh/t-uclinux	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/sh/t-uclinux	2010-03-30 10:39:22.000000000 +0300
@@ -0,0 +1,4 @@
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o $(OPT_EXTRA_PARTS)
diff -Naur a/src/gcc/config/sh/uclinux.h b/src/gcc/config/sh/uclinux.h
--- a/src/gcc/config/sh/uclinux.h	1970-01-01 02:00:00.000000000 +0200
+++ b/src/gcc/config/sh/uclinux.h	2010-03-30 10:39:22.000000000 +0300
@@ -0,0 +1,104 @@
+/* Definitions for SH based uClinux system using ELF objects with
+   special linker post-processing to produce FLAT executables.
+
+   Copyright (C) 2008
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared:crt1.o%s} crti.o%s \
+   %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}" \
+   FDPIC_STARTFILE_SPEC
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+#define LINK_EH_SPEC "%{mfdpic:%{!static:--eh-frame-hdr}} "
+
+#ifdef FDPIC_DEFAULT
+#undef SUBTARGET_LINK_SPEC
+#define SUBTARGET_LINK_SPEC \
+  "%{shared:-shared} \
+   %{!static: \
+     %{rdynamic:-export-dynamic} \
+     %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
+   %{static:-static}"
+#undef SUBTARGET_LINK_EMUL_SUFFIX
+#define SUBTARGET_LINK_EMUL_SUFFIX "_fd"
+#undef SUBTARGET_DRIVER_SELF_SPECS
+#define SUBTARGET_DRIVER_SELF_SPECS "%{!mno-fdpic:-mfdpic} "
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "%{!mno-fdpic:--fdpic}"
+#define FDPIC_STARTFILE_SPEC "%{!mno-fdpic: crtreloc.o%s}"
+#else
+#undef SUBTARGET_LINK_SPEC
+#define SUBTARGET_LINK_SPEC "%{shared:-shared} %{static:-static} %{!elf2flt*:-elf2flt}"
+#undef SUBTARGET_LINK_EMUL_SUFFIX
+#define SUBTARGET_LINK_EMUL_SUFFIX "_uclinux"
+#define FDPIC_STARTFILE_SPEC "%{mfdpic: crtreloc.o%s}"
+#endif
+
+/* While the speed-optimized implementations of udivsi3_i4i / sdivsi3_i4i
+   in libgcc are not available for SH2, the space-optimized ones in
+   libgcc-Os-4-200 are.  Thus, when not optimizing for space, link
+   libgcc-Os-4-200 after libgcc, so that -mdiv=call-table works for -m2.  */
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "%{Os: -lgcc-Os-4-200} -lgcc %{!Os: -lgcc-Os-4-200}"
+
+/* we have init/fini section. */
+#define HAS_INIT_SECTION
+
+/* Bring in standard linux defines */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS()		\
+  do						\
+    {						\
+	builtin_define ("__gnu_linux__");	\
+	builtin_define_std ("linux");		\
+	builtin_define_std ("unix");		\
+	builtin_assert ("system=linux");	\
+	builtin_assert ("system=unix");		\
+	builtin_assert ("system=posix");	\
+	builtin_define ("__uClinux__");		\
+    }						\
+  while (0)
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+/* Since libgcc is compiled with -fpic for this target, we can't use
+   __sdivsi3_1 as the division strategy for -O0 and -Os.  */
+#undef SH_DIV_STRATEGY_DEFAULT
+#define SH_DIV_STRATEGY_DEFAULT SH_DIV_CALL2
+#undef SH_DIV_STR_FOR_SIZE
+#define SH_DIV_STR_FOR_SIZE "call2"
+
+/* The uclinux binary format relies on relocations against a segment being
+   within that segment.  Conservatively apply this rule to individual
+   sections.  */
+#undef SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
+#define SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 1
+
+/* CSL LOCAL */
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS					\
+do {									\
+  /* __thread is not supported by uClibc.  */				\
+  targetm.have_tls = 0;							\
+} while (0)
diff -Naur a/src/gcc/config/t-eglibc b/src/gcc/config/t-eglibc
--- a/src/gcc/config/t-eglibc	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/config/t-eglibc	2010-03-30 10:39:45.000000000 +0300
@@ -10,7 +10,7 @@
 	'{ \
 	N=split ($$0, configs, ","); \
 	for (i = 1; i < N; ++i) $1; \
-	$2; \
+	if (N > 0) $2; \
 	}')
 
 MULTILIB_OPTIONS    := $(call EGLIBC_AWK, \
diff -Naur a/src/gcc/config.gcc b/src/gcc/config.gcc
--- a/src/gcc/config.gcc	2009-10-14 21:55:24.000000000 +0300
+++ b/src/gcc/config.gcc	2010-04-10 10:19:18.000000000 +0300
@@ -209,6 +209,7 @@
 # Avoid generic cases below matching.
    h8300-*-rtems* | h8300-*-elf* \
  | sh-*-elf* | sh-*-symbianelf* | sh-*-linux* | sh-*-netbsdelf* \
+ | sh-*-uclinux* \
  | sh-*-rtems* | sh-wrs-vxworks) ;;
    arm-*-coff*		\
  | armel-*-coff*	\
@@ -780,7 +781,7 @@
 	tmake_file="arm/t-arm arm/t-arm-elf"
 	tmake_file="${tmake_file} arm/t-arm-softfp soft-fp/t-softfp"
 	;;
-arm*-*-eabi* | arm*-*-symbianelf* )
+arm*-*-eabi* | arm*-*-nucleuseabi* | arm*-*-symbianelf* )
 	# The BPABI long long divmod functions return a 128-bit value in
 	# registers r0-r3.  Correctly modeling that requires the use of
 	# TImode.
@@ -789,9 +790,20 @@
 	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
 	tmake_file="arm/t-arm arm/t-arm-elf"
 	case ${target} in
-	arm*-*-eabi*)
+	arm*-*-eabi* | arm*-*-nucleuseabi*)
 	  tm_file="$tm_file arm/eabi.h"
 	  tm_file="${tm_file} arm/nocrt0.h"
+	  case ${target} in
+	    *samsung-nucleuseabi*)
+	      tm_file="$tm_file arm/nucleus.h"
+	      tmake_file="${tmake_file} t-slibgcc-elf-ver t-libc-ok"
+	      tmake_file="${tmake_file} t-libgcc-pic arm/t-nucleus"
+	      tm_defines="${tm_defines} NUCLEUS_SHARED_EXEC=1"
+	      ;;
+	    *nucleuseabi*)
+	      tm_file="$tm_file arm/nucleus.h"
+	      ;;
+	  esac
 	  tmake_file="${tmake_file} arm/t-bpabi"
 	  extra_options="${extra_options} arm/eabi.opt"
 	  if test x$enable_extra_sgxx_multilibs = xyes; then
@@ -802,9 +814,7 @@
 	  ;;
 	arm*-*-symbianelf*)
 	  tm_file="${tm_file} arm/symbian.h"
-	  # We do not include t-bpabi for Symbian OS because the system
-	  # provides its own implementation of the BPABI functions.
-	  tmake_file="${tmake_file} arm/t-symbian"
+	  tmake_file="${tmake_file} arm/t-bpabi arm/t-symbian"
 	  ;;
 	esac
 	tm_file="${tm_file} arm/aout.h arm/arm.h"
@@ -1310,6 +1320,23 @@
 		thread_file='posix'
 	fi
 	;;
+arm-*-mingw32*)
+        tm_file="arm/semi.h arm/aout.h ${tm_file} arm/coff.h dbxcoff.h arm/pe.h arm/wince-pe.h arm/mingw32.h"
+        tmake_file="${tmake_file} arm/t-arm arm/t-wince-pe arm/t-cygming arm/t-mingw32"
+        target_gtfiles="\$(srcdir)/config/arm/pe.c"
+        extra_options="${extra_options} arm/pe.opt arm/cygming.opt"
+        extra_objs="pe.o pe-stubs.o"
+        c_target_objs="${c_target_objs} msformat-c.o"
+        cxx_target_objs="pe-cxx.o msformat-c.o"
+        default_use_cxa_atexit=yes
+        case ${enable_threads} in
+          "" | yes | win32)
+          thread_file='win32'
+          tmake_file="${tmake_file} i386/t-gthr-win32"
+          ;;
+        esac
+        tmake_file="${tmake_file} arm/t-arm-softfp soft-fp/t-softfp"
+        ;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
 	xm_file=i386/xm-mingw32.h
@@ -1905,7 +1932,7 @@
 powerpc-*-eabi*)
 	tm_file="${tm_file} dbxelf.h elfos.h usegas.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h"
 	extra_options="${extra_options} rs6000/sysv4.opt"
-	tmake_file="rs6000/t-fprules rs6000/t-fprules-fpbit rs6000/t-ppcgas rs6000/t-ppccomm"
+	tmake_file="rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcgas rs6000/t-ppccomm"
 	if test x$enable_extra_sgxx_multilibs = xyes; then
 	  tmake_file="${tmake_file} rs6000/t-cs-eabi"
 	elif test x$enable_extra_sgxxlite_multilibs = xyes; then
@@ -2115,6 +2142,7 @@
 sh-*-elf* | sh[12346l]*-*-elf* | \
 sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
   sh-*-linux* | sh[2346lbe]*-*-linux* | \
+  sh-*-uclinux* | sh[12]-*-uclinux* | \
   sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
    sh64-*-netbsd* | sh64l*-*-netbsd*)
 	tmake_file="${tmake_file} sh/t-sh sh/t-elf"
@@ -2152,6 +2180,13 @@
 	sh*-*-linux*)	tmake_file="${tmake_file} sh/t-linux"
 			tm_file="${tm_file} linux.h sh/linux.h" ;;
 	sh*-*-netbsd*)	tm_file="${tm_file} netbsd.h netbsd-elf.h sh/netbsd-elf.h" ;;
+	sh*-*-uclinux*)	if test x$enable_fdpic != xno; then
+				tmake_file="${tmake_file} t-slibgcc-elf-ver"
+				tm_file="${tm_file} sh/uclinux.h"
+				tm_defines="$tm_defines FDPIC_DEFAULT=1"
+			else
+				tm_file="${tm_file} flat.h sh/uclinux.h"
+			fi ;;
 	sh*-superh-elf)	if test x$with_libgloss != xno; then
 				with_libgloss=yes
 				tm_file="${tm_file} sh/newlib.h"
@@ -2177,6 +2212,7 @@
 	*-*-netbsd)
                 tmake_file="${tmake_file} sh/t-netbsd"
 		;;
+	sh*-*-uclinux*)	tmake_file="${tmake_file} sh/t-uclinux" ;;
 	sh64*-*-linux*)
 		tmake_file="${tmake_file} sh/t-sh64 sh/t-linux64"
 		tm_file="${tm_file} sh/sh64.h"
@@ -3057,8 +3093,8 @@
 			| power | power[234567] | power6x | powerpc | powerpc64 \
 			| rios | rios1 | rios2 | rsc | rsc1 | rs64a \
 			| 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
-			| 505 | 601 | 602 | 603 | 603e | ec603e | 604 \
-			| 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
+			| 476 | 476fp | 505 | 601 | 602 | 603 | 603e | ec603e \
+			| 604 | 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
 			| e300c[23] | 854[08] | e500mc \
 			| 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
 				# OK
@@ -3237,10 +3273,16 @@
 			tm_defines="US_SOFTWARE_GOFAST $tm_defines"
 			tmake_file="mips/t-gofast $tmake_file"
 		else
-			tmake_file="mips/t-mips $tmake_file"
+			case ${target} in
+				mips*-sde-elf*)
+					tmake_file="mips/t-fprules-softfp soft-fp/t-softfp $tmake_file"
+					;;
+				*)
+					tmake_file="mips/t-mips $tmake_file"
+					;;
+			esac
 		fi
 		;;
-
 	powerpc*-*-* | rs6000-*-*)
 		# FIXME: The PowerPC port uses the value set at compile time,
 		# although it's only cosmetic.
diff -Naur a/src/gcc/config.in b/src/gcc/config.in
--- a/src/gcc/config.in	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/config.in	2010-04-01 10:18:59.000000000 +0300
@@ -212,6 +212,12 @@
 #endif
 
 
+/* Define if your assembler supports the DCI/ICI instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DCI
+#endif
+
+
 /* Define if your assembler supports the --debug-prefix-map option. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_DEBUG_PREFIX_MAP
@@ -864,6 +870,12 @@
 #endif
 
 
+/* Define 0/1 if your assembler supports .cfi_sections. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_CFI_SECTIONS_DIRECTIVE
+#endif
+
+
 /* Define if your assembler uses the new HImode fild and fist notation. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GAS_FILDS_FISTS
diff -Naur a/src/gcc/configure b/src/gcc/configure
--- a/src/gcc/configure	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/configure	2010-04-01 10:18:55.000000000 +0300
@@ -15020,6 +15020,10 @@
   lt_cv_file_magic_cmd='$OBJDUMP -f'
   ;;
 
+nucleuseabi*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
 darwin* | rhapsody*)
   lt_cv_deplibs_check_method=pass_all
   ;;
@@ -15781,7 +15785,7 @@
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 15784 "configure"' > conftest.$ac_ext
+  echo '#line 15788 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -17080,11 +17084,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17083: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17087: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17087: \$? = $ac_status" >&5
+   echo "$as_me:17091: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -17419,11 +17423,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17422: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17426: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17426: \$? = $ac_status" >&5
+   echo "$as_me:17430: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -17524,11 +17528,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17527: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17531: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17531: \$? = $ac_status" >&5
+   echo "$as_me:17535: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -17579,11 +17583,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17582: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17586: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17586: \$? = $ac_status" >&5
+   echo "$as_me:17590: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -19478,6 +19482,21 @@
   shlibpath_overrides_runpath=yes
   ;;
 
+nucleus*)
+  case $host_vendor in
+    samsung)
+      version_type=linux
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+      soname_spec='$libname${shared_ext}$major'
+      shlibpath_var=LD_LIBRARY_PATH
+      hardcode_into_libs=yes
+      ;;
+    *)
+      dynamic_linker=no
+      ;;
+  esac
+  ;;
+
 *nto* | *qnx*)
   version_type=qnx
   need_lib_prefix=no
@@ -20391,7 +20410,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 20394 "configure"
+#line 20413 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -20487,7 +20506,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 20490 "configure"
+#line 20509 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -21789,6 +21808,42 @@
 _ACEOF
 
 
+echo "$as_me:$LINENO: checking assembler for cfi sections directive" >&5
+echo $ECHO_N "checking assembler for cfi sections directive... $ECHO_C" >&6
+if test "${gcc_cv_as_cfi_sections_directive+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  gcc_cv_as_cfi_sections_directive=no
+  if test x$gcc_cv_as != x; then
+    echo '	.text
+	.cfi_sections .debug_frame, .eh_frame
+	.cfi_startproc
+	.cfi_endproc' > conftest.s
+    if { ac_try='$gcc_cv_as  -o conftest.o conftest.s >&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }
+    then
+	gcc_cv_as_cfi_sections_directive=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_cfi_sections_directive" >&5
+echo "${ECHO_T}$gcc_cv_as_cfi_sections_directive" >&6
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_CFI_SECTIONS_DIRECTIVE `if test $gcc_cv_as_cfi_sections_directive = yes;
+    then echo 1; else echo 0; fi`
+_ACEOF
+
+
 # GAS versions up to and including 2.11.0 may mis-optimize
 # .eh_frame data.
 echo "$as_me:$LINENO: checking assembler for eh_frame optimization" >&5
@@ -23617,6 +23672,52 @@
 
 fi
 
+    case $target in
+      *-*-aix*) conftest_s='	.machine "476"
+	.csect .text[PR]
+	dci 0';;
+      *) conftest_s='	.machine "476"
+	.text
+	dci 0';;
+    esac
+
+    echo "$as_me:$LINENO: checking assembler for data cache invalidate support" >&5
+echo $ECHO_N "checking assembler for data cache invalidate support... $ECHO_C" >&6
+if test "${gcc_cv_as_powerpc_dci+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  gcc_cv_as_powerpc_dci=no
+    if test $in_tree_gas = yes; then
+    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
+  then gcc_cv_as_powerpc_dci=yes
+fi
+  elif test x$gcc_cv_as != x; then
+    echo "$conftest_s" > conftest.s
+    if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }
+    then
+	gcc_cv_as_powerpc_dci=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_dci" >&5
+echo "${ECHO_T}$gcc_cv_as_powerpc_dci" >&6
+if test $gcc_cv_as_powerpc_dci = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_DCI 1
+_ACEOF
+
+fi
+
     echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5
 echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6
 if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then
@@ -24398,6 +24499,9 @@
       else
 	glibc_header_dir=/usr/include
       fi
+      if test "x$enable_libssp" = "xno"; then
+	gcc_cv_libc_provides_ssp=yes
+      fi
       # glibc 2.4 and later provides __stack_chk_fail and
       # either __stack_chk_guard, or TLS access to stack guard canary.
       if test -f $glibc_header_dir/features.h \
@@ -24782,8 +24886,8 @@
 rm -f Make-hooks
 touch Make-hooks
 target_list="all.cross start.encap rest.encap tags \
-	install-common install-man install-info install-pdf dvi pdf \
-	html uninstall info man srcextra srcman srcinfo \
+	install-common install-man install-info install-pdf install-html dvi \
+	pdf html uninstall info man srcextra srcman srcinfo \
 	mostlyclean clean distclean maintainer-clean"
 
 for t in $target_list
diff -Naur a/src/gcc/configure.ac b/src/gcc/configure.ac
--- a/src/gcc/configure.ac	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/configure.ac	2010-04-01 10:18:55.000000000 +0300
@@ -2322,6 +2322,17 @@
     then echo 1; else echo 0; fi`],
   [Define 0/1 if your assembler supports .cfi_personality.])
 
+gcc_GAS_CHECK_FEATURE([cfi sections directive],
+  gcc_cv_as_cfi_sections_directive, ,,
+[	.text
+	.cfi_sections .debug_frame, .eh_frame
+	.cfi_startproc
+	.cfi_endproc])
+AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_SECTIONS_DIRECTIVE,
+  [`if test $gcc_cv_as_cfi_sections_directive = yes;
+    then echo 1; else echo 0; fi`],
+  [Define 0/1 if your assembler supports .cfi_sections.])
+
 # GAS versions up to and including 2.11.0 may mis-optimize
 # .eh_frame data.
 gcc_GAS_CHECK_FEATURE(eh_frame optimization, gcc_cv_as_eh_frame,
@@ -3210,6 +3221,21 @@
       [AC_DEFINE(HAVE_AS_VSX, 1,
 	  [Define if your assembler supports VSX instructions.])])
 
+    case $target in
+      *-*-aix*) conftest_s='	.machine "476"
+	.csect .text[[PR]]
+	dci 0';;
+      *) conftest_s='	.machine "476"
+	.text
+	dci 0';;
+    esac
+
+    gcc_GAS_CHECK_FEATURE([data cache invalidate support],
+      gcc_cv_as_powerpc_dci, [9,99,0], -a32,
+      [$conftest_s],,
+      [AC_DEFINE(HAVE_AS_DCI, 1,
+	  [Define if your assembler supports the DCI/ICI instructions.])])
+
     gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
       gcc_cv_as_powerpc_gnu_attribute, [2,18,0],,
       [.gnu_attribute 4,1],,
@@ -3597,6 +3623,9 @@
       else
 	glibc_header_dir=/usr/include
       fi
+      if test "x$enable_libssp" = "xno"; then
+	gcc_cv_libc_provides_ssp=yes
+      fi
       # glibc 2.4 and later provides __stack_chk_fail and
       # either __stack_chk_guard, or TLS access to stack guard canary.
       if test -f $glibc_header_dir/features.h \
@@ -3866,8 +3895,8 @@
 rm -f Make-hooks
 touch Make-hooks
 target_list="all.cross start.encap rest.encap tags \
-	install-common install-man install-info install-pdf dvi pdf \
-	html uninstall info man srcextra srcman srcinfo \
+	install-common install-man install-info install-pdf install-html dvi \
+	pdf html uninstall info man srcextra srcman srcinfo \
 	mostlyclean clean distclean maintainer-clean"
 
 for t in $target_list
diff -Naur a/src/gcc/cp/cp-tree.h b/src/gcc/cp/cp-tree.h
--- a/src/gcc/cp/cp-tree.h	2009-10-12 21:19:58.000000000 +0300
+++ b/src/gcc/cp/cp-tree.h	2010-04-02 10:28:17.000000000 +0300
@@ -880,7 +880,8 @@
    expression for `*this'.  */
 
 #define current_class_ptr \
-  (cfun ? cp_function_chain->x_current_class_ptr : NULL_TREE)
+  (cfun && cp_function_chain					\
+   ? cp_function_chain->x_current_class_ptr : NULL_TREE)
 #define current_class_ref \
   (cfun ? cp_function_chain->x_current_class_ref : NULL_TREE)
 
@@ -4614,6 +4615,8 @@
 extern bool reregister_specialization		(tree, tree, tree);
 extern tree fold_non_dependent_expr		(tree);
 extern bool explicit_class_specialization_p     (tree);
+extern int push_tinst_level                     (tree);
+extern void pop_tinst_level                     (void);
 extern struct tinst_level *outermost_tinst_level(void);
 extern bool parameter_of_template_p		(tree, tree);
 
diff -Naur a/src/gcc/cp/Make-lang.in b/src/gcc/cp/Make-lang.in
--- a/src/gcc/cp/Make-lang.in	2009-10-12 21:19:58.000000000 +0300
+++ b/src/gcc/cp/Make-lang.in	2010-03-30 10:38:14.000000000 +0300
@@ -24,7 +24,7 @@
 #
 # foo.all.cross, foo.start.encap, foo.rest.encap,
 # foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
-# foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
 # foo.mostlyclean, foo.clean, foo.distclean,
 # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
 #
@@ -120,6 +120,7 @@
 c++.dvi:
 c++.pdf:
 c++.install-pdf:
+c++.install-html:
 c++.html:
 c++.srcinfo:
 c++.srcextra:
diff -Naur a/src/gcc/cp/mangle.c b/src/gcc/cp/mangle.c
--- a/src/gcc/cp/mangle.c	2009-10-12 21:19:58.000000000 +0300
+++ b/src/gcc/cp/mangle.c	2010-03-30 10:38:14.000000000 +0300
@@ -2776,6 +2776,22 @@
 mangle_decl_string (const tree decl)
 {
   tree result;
+  location_t saved_loc = input_location;
+  tree saved_fn = NULL_TREE;
+  bool template_p = false;
+
+  if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+    {
+      struct tinst_level *tl = current_instantiation ();
+      if (!tl || tl->decl != decl)
+	{
+	  template_p = true;
+	  saved_fn = current_function_decl;
+	  push_tinst_level (decl);
+	  current_function_decl = NULL_TREE;
+	}
+    }
+  input_location = DECL_SOURCE_LOCATION (decl);
 
   start_mangling (decl);
 
@@ -2788,6 +2804,14 @@
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_decl_string = '%s'\n\n",
 	     IDENTIFIER_POINTER (result));
+
+  if (template_p)
+    {
+      pop_tinst_level ();
+      current_function_decl = saved_fn;
+    }
+  input_location = saved_loc;
+
   return result;
 }
 
diff -Naur a/src/gcc/cp/name-lookup.h b/src/gcc/cp/name-lookup.h
--- a/src/gcc/cp/name-lookup.h	2009-10-12 21:19:58.000000000 +0300
+++ b/src/gcc/cp/name-lookup.h	2010-03-30 10:38:14.000000000 +0300
@@ -263,7 +263,7 @@
 /* The binding level currently in effect.  */
 
 #define current_binding_level			\
-  (*(cfun && cp_function_chain->bindings	\
+  (*(cfun && cp_function_chain && cp_function_chain->bindings \
    ? &cp_function_chain->bindings		\
    : &scope_chain->bindings))
 
diff -Naur a/src/gcc/cp/pt.c b/src/gcc/cp/pt.c
--- a/src/gcc/cp/pt.c	2009-10-12 21:19:58.000000000 +0300
+++ b/src/gcc/cp/pt.c	2010-03-30 10:38:14.000000000 +0300
@@ -105,8 +105,6 @@
 			     unification_kind_t, int, bool);
 static int unify (tree, tree, tree, tree, int);
 static void add_pending_template (tree);
-static int push_tinst_level (tree);
-static void pop_tinst_level (void);
 static tree reopen_tinst_level (struct tinst_level *);
 static tree tsubst_initializer_list (tree, tree);
 static tree get_class_bindings (tree, tree, tree);
@@ -6359,7 +6357,7 @@
 /* We're starting to instantiate D; record the template instantiation context
    for diagnostics and to restore it later.  */
 
-static int
+int
 push_tinst_level (tree d)
 {
   struct tinst_level *new_level;
@@ -6402,7 +6400,7 @@
 /* We're done instantiating this template; return to the instantiation
    context.  */
 
-static void
+void
 pop_tinst_level (void)
 {
   /* Restore the filename and line number stashed away when we started
diff -Naur a/src/gcc/cp/typeck2.c b/src/gcc/cp/typeck2.c
--- a/src/gcc/cp/typeck2.c	2009-10-12 21:19:58.000000000 +0300
+++ b/src/gcc/cp/typeck2.c	2010-04-10 10:19:15.000000000 +0300
@@ -451,13 +451,15 @@
    expression to which INIT should be assigned.  INIT is a CONSTRUCTOR.  */
 
 static void
-split_nonconstant_init_1 (tree dest, tree init)
+split_nonconstant_init_1 (tree dest, tree *initp)
 {
   unsigned HOST_WIDE_INT idx;
+  tree init = *initp;
   tree field_index, value;
   tree type = TREE_TYPE (dest);
   tree inner_type = NULL;
   bool array_type_p = false;
+  HOST_WIDE_INT num_type_elements, num_initialized_elements;
 
   switch (TREE_CODE (type))
     {
@@ -469,6 +471,7 @@
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
+      num_initialized_elements = 0;
       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
 				field_index, value)
 	{
@@ -491,12 +494,13 @@
 		sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
 			      NULL_TREE);
 
-	      split_nonconstant_init_1 (sub, value);
+	      split_nonconstant_init_1 (sub, &value);
 	    }
 	  else if (!initializer_constant_valid_p (value, inner_type))
 	    {
 	      tree code;
 	      tree sub;
+	      HOST_WIDE_INT inner_elements;
 
 	      /* FIXME: Ordered removal is O(1) so the whole function is
 		 worst-case quadratic. This could be fixed using an aside
@@ -519,9 +523,22 @@
 	      code = build2 (INIT_EXPR, inner_type, sub, value);
 	      code = build_stmt (EXPR_STMT, code);
 	      add_stmt (code);
+
+	      inner_elements = count_type_elements (inner_type, true);
+	      if (inner_elements < 0)
+		num_initialized_elements = -1;
+	      else if (num_initialized_elements >= 0)
+		num_initialized_elements += inner_elements;
 	      continue;
 	    }
 	}
+
+      num_type_elements = count_type_elements (type, true);
+      /* If all elements of the initializer are non-constant and
+	 have been split out, we don't need the empty CONSTRUCTOR.  */
+      if (num_type_elements > 0
+	  && num_type_elements == num_initialized_elements)
+	*initp = NULL;
       break;
 
     case VECTOR_TYPE:
@@ -557,7 +574,7 @@
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
       code = push_stmt_list ();
-      split_nonconstant_init_1 (dest, init);
+      split_nonconstant_init_1 (dest, &init);
       code = pop_stmt_list (code);
       DECL_INITIAL (dest) = init;
       TREE_READONLY (dest) = 0;
diff -Naur a/src/gcc/dbxout.c b/src/gcc/dbxout.c
--- a/src/gcc/dbxout.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/dbxout.c	2010-03-30 10:39:47.000000000 +0300
@@ -349,6 +349,7 @@
 {
   dbxout_init,
   dbxout_finish,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   dbxout_start_source_file,
@@ -386,6 +387,7 @@
 {
   dbxout_init,
   dbxout_finish,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   dbxout_start_source_file,
diff -Naur a/src/gcc/debug.c b/src/gcc/debug.c
--- a/src/gcc/debug.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/debug.c	2010-03-30 10:39:47.000000000 +0300
@@ -27,6 +27,7 @@
 {
   debug_nothing_charstar,
   debug_nothing_charstar,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
diff -Naur a/src/gcc/debug.h b/src/gcc/debug.h
--- a/src/gcc/debug.h	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/debug.h	2010-03-30 10:39:47.000000000 +0300
@@ -31,6 +31,10 @@
   /* Output debug symbols.  */
   void (* finish) (const char *main_filename);
 
+  /* Called from cgraph_optimize before starting to assemble
+     functions/variables/toplevel asms.  */
+  void (* assembly_start) (void);
+
   /* Macro defined on line LINE with name and expansion TEXT.  */
   void (* define) (unsigned int line, const char *text);
 
diff -Naur a/src/gcc/defaults.h b/src/gcc/defaults.h
--- a/src/gcc/defaults.h	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/defaults.h	2010-03-30 10:39:46.000000000 +0300
@@ -501,6 +501,10 @@
 #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
 #endif
 
+#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 0
+#endif
+
 #ifndef TARGET_DLLIMPORT_DECL_ATTRIBUTES
 #define TARGET_DLLIMPORT_DECL_ATTRIBUTES 0
 #endif
diff -Naur a/src/gcc/df-scan.c b/src/gcc/df-scan.c
--- a/src/gcc/df-scan.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/df-scan.c	2010-03-30 10:39:47.000000000 +0300
@@ -3952,14 +3952,13 @@
 #endif
     }
 
-#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
   /* Many architectures have a GP register even without flag_pic.
      Assume the pic register is not in use, or will be handled by
      other means, if it is not fixed.  */
-  if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+  if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+      && (unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
       && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
     bitmap_set_bit (exit_block_uses, PIC_OFFSET_TABLE_REGNUM);
-#endif
   
   /* Mark all global registers, and all registers used by the
      epilogue as being live at the end of the function since they
diff -Naur a/src/gcc/doc/arm-neon-intrinsics.texi b/src/gcc/doc/arm-neon-intrinsics.texi
--- a/src/gcc/doc/arm-neon-intrinsics.texi	2009-10-12 21:15:43.000000000 +0300
+++ b/src/gcc/doc/arm-neon-intrinsics.texi	2010-03-30 10:32:30.000000000 +0300
@@ -4696,7 +4696,7 @@
 
 @itemize @bullet
 @item uint32_t vget_lane_u32 (uint32x2_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov.u32 @var{r0}, @var{d0}[@var{0}]}
+@*@emph{Form of expected instruction(s):} @code{vmov.32 @var{r0}, @var{d0}[@var{0}]}
 @end itemize
 
 
@@ -4714,7 +4714,7 @@
 
 @itemize @bullet
 @item int32_t vget_lane_s32 (int32x2_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov.s32 @var{r0}, @var{d0}[@var{0}]}
+@*@emph{Form of expected instruction(s):} @code{vmov.32 @var{r0}, @var{d0}[@var{0}]}
 @end itemize
 
 
@@ -4732,7 +4732,7 @@
 
 @itemize @bullet
 @item float32_t vget_lane_f32 (float32x2_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov.f32 @var{r0}, @var{d0}[@var{0}]}
+@*@emph{Form of expected instruction(s):} @code{vmov.32 @var{r0}, @var{d0}[@var{0}]}
 @end itemize
 
 
@@ -4750,19 +4750,17 @@
 
 @itemize @bullet
 @item uint64_t vget_lane_u64 (uint64x1_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{r0}, @var{r0}, @var{d0}}
 @end itemize
 
 
 @itemize @bullet
 @item int64_t vget_lane_s64 (int64x1_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{r0}, @var{r0}, @var{d0}}
 @end itemize
 
 
 @itemize @bullet
 @item uint32_t vgetq_lane_u32 (uint32x4_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov.u32 @var{r0}, @var{d0}[@var{0}]}
+@*@emph{Form of expected instruction(s):} @code{vmov.32 @var{r0}, @var{d0}[@var{0}]}
 @end itemize
 
 
@@ -4780,7 +4778,7 @@
 
 @itemize @bullet
 @item int32_t vgetq_lane_s32 (int32x4_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov.s32 @var{r0}, @var{d0}[@var{0}]}
+@*@emph{Form of expected instruction(s):} @code{vmov.32 @var{r0}, @var{d0}[@var{0}]}
 @end itemize
 
 
@@ -4798,7 +4796,7 @@
 
 @itemize @bullet
 @item float32_t vgetq_lane_f32 (float32x4_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov.f32 @var{r0}, @var{d0}[@var{0}]}
+@*@emph{Form of expected instruction(s):} @code{vmov.32 @var{r0}, @var{d0}[@var{0}]}
 @end itemize
 
 
@@ -4886,13 +4884,11 @@
 
 @itemize @bullet
 @item uint64x1_t vset_lane_u64 (uint64_t, uint64x1_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{d0}, @var{r0}, @var{r0}}
 @end itemize
 
 
 @itemize @bullet
 @item int64x1_t vset_lane_s64 (int64_t, int64x1_t, const int)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{d0}, @var{r0}, @var{r0}}
 @end itemize
 
 
@@ -5081,13 +5077,11 @@
 
 @itemize @bullet
 @item uint64x1_t vdup_n_u64 (uint64_t)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{d0}, @var{r0}, @var{r0}}
 @end itemize
 
 
 @itemize @bullet
 @item int64x1_t vdup_n_s64 (int64_t)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{d0}, @var{r0}, @var{r0}}
 @end itemize
 
 
@@ -5213,13 +5207,11 @@
 
 @itemize @bullet
 @item uint64x1_t vmov_n_u64 (uint64_t)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{d0}, @var{r0}, @var{r0}}
 @end itemize
 
 
 @itemize @bullet
 @item int64x1_t vmov_n_s64 (int64_t)
-@*@emph{Form of expected instruction(s):} @code{vmov @var{d0}, @var{r0}, @var{r0}}
 @end itemize
 
 
diff -Naur a/src/gcc/doc/extend.texi b/src/gcc/doc/extend.texi
--- a/src/gcc/doc/extend.texi	2009-10-12 21:15:43.000000000 +0300
+++ b/src/gcc/doc/extend.texi	2010-03-30 10:32:30.000000000 +0300
@@ -2605,6 +2605,25 @@
 may interact badly with some GCC extensions such as @code{__builtin_apply}
 (@pxref{Constructing Calls}).
 
+@item micromips/nomicromips
+@cindex @code{micromips} attribute
+@cindex @code{nomicromips} attribute
+
+On MIPS targets, you can use the @code{micromips} and @code{nomicromips}
+function attributes to locally select or turn off microMIPS code generation.
+A function with the @code{micromips} attribute is emitted as microMIPS code,
+while microMIPS code generation is disabled for functions with the
+@code{nomicromips} attribute.  These attributes override the
+@option{-mmicromips} and @option{-mno-micromips} options on the command line
+(@pxref{MIPS Options}).
+
+When compiling files containing mixed microMIPS and non-microMIPS code, the
+preprocessor symbol @code{__mips_micromips} reflects the setting on the
+command line,
+not that within individual functions.  Mixed microMIPS and non-microMIPS code
+may interact badly with some GCC extensions such as @code{__builtin_apply}
+(@pxref{Constructing Calls}).
+
 @item model (@var{model-name})
 @cindex function addressability on the M32R/D
 @cindex variable addressability on the IA-64
diff -Naur a/src/gcc/doc/install.texi b/src/gcc/doc/install.texi
--- a/src/gcc/doc/install.texi	2009-10-12 21:15:43.000000000 +0300
+++ b/src/gcc/doc/install.texi	2010-03-30 10:32:30.000000000 +0300
@@ -1487,6 +1487,10 @@
 128-bit @code{long double} when built against GNU C Library 2.4 and later,
 64-bit @code{long double} otherwise.
 
+@item --enable-fdpic
+On SH uClinux systems, generate ELF FDPIC code rather than code
+expected to be postprocessed into the FLT binary format.
+
 @item --with-gmp=@var{pathname}
 @itemx --with-gmp-include=@var{pathname}
 @itemx --with-gmp-lib=@var{pathname}
diff -Naur a/src/gcc/doc/invoke.texi b/src/gcc/doc/invoke.texi
--- a/src/gcc/doc/invoke.texi	2009-10-12 21:15:43.000000000 +0300
+++ b/src/gcc/doc/invoke.texi	2010-04-01 10:18:54.000000000 +0300
@@ -659,6 +659,7 @@
 -mshared  -mno-shared  -mplt  -mno-plt  -mxgot  -mno-xgot @gol
 -mgp32  -mgp64  -mfp32  -mfp64  -mhard-float  -msoft-float @gol
 -msingle-float  -mdouble-float  -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol
+-mmicromips -mno-micromips -mmcu -mmno-mcu @gol
 -mfpu=@var{fpu-type} @gol
 -msmartmips  -mno-smartmips @gol
 -mpaired-single  -mno-paired-single  -mdmx  -mno-mdmx @gol
@@ -674,6 +675,7 @@
 -mcheck-zero-division  -mno-check-zero-division @gol
 -mdivide-traps  -mdivide-breaks @gol
 -mmemcpy  -mno-memcpy  -mlong-calls  -mno-long-calls @gol
+-mjals -mno-jals @gol
 -mmad  -mno-mad  -mfused-madd  -mno-fused-madd  -nocpp @gol
 -mfix-r4000  -mno-fix-r4000  -mfix-r4400  -mno-fix-r4400 @gol
 -mfix-r10000 -mno-fix-r10000  -mfix-vr4120  -mno-fix-vr4120 @gol
@@ -740,6 +742,7 @@
 -mcall-sysv  -mcall-netbsd @gol
 -maix-struct-return  -msvr4-struct-return @gol
 -mabi=@var{abi-type} -msecure-plt -mbss-plt @gol
+-mblock-move-inline-limit=@var{num} @gol
 -misel -mno-isel @gol
 -misel=yes  -misel=no @gol
 -mspe -mno-spe @gol
@@ -784,7 +787,7 @@
 -mprefergot  -musermode -multcost=@var{number} -mdiv=@var{strategy} @gol
 -mdivsi3_libfunc=@var{name} -mfixed-range=@var{register-range} @gol
 -madjust-unroll -mindexed-addressing -mgettrcost=@var{number} -mpt-fixed @gol
--minvalid-symbols}
+-minvalid-symbols  -mfdpic}
 
 @emph{SPARC Options}
 @gccoptlist{-mcpu=@var{cpu-type} @gol
@@ -5946,7 +5949,7 @@
 by allowing other instructions to be issued until the result of the load
 or floating point instruction is required.
 
-Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+Enabled at levels @option{-O2}, @option{-O3}.
 
 @item -fschedule-insns2
 @opindex fschedule-insns2
@@ -9095,7 +9098,7 @@
 @samp{arm1136j-s}, @samp{arm1136jf-s}, @samp{mpcore}, @samp{mpcorenovfp},
 @samp{arm1156t2-s}, @samp{arm1176jz-s}, @samp{arm1176jzf-s},
 @samp{cortex-a5}, @samp{cortex-a8}, @samp{cortex-a9},
-@samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-m3},
+@samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-m4}, @samp{cortex-m3},
 @samp{cortex-m1}, @samp{cortex-m0},
 @samp{xscale}, @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}, @samp{marvell-f}.
 
@@ -12578,7 +12581,7 @@
 @samp{74kc}, @samp{74kf2_1}, @samp{74kf1_1}, @samp{74kf3_2},
 @samp{1004kc}, @samp{1004kf2_1}, @samp{1004kf1_1},
 @samp{loongson2e}, @samp{loongson2f},
-@samp{m4k},
+@samp{m4k}, @samp{m14k},
 @samp{octeon},
 @samp{orion},
 @samp{r2000}, @samp{r3000}, @samp{r3900}, @samp{r4000}, @samp{r4400},
@@ -12699,13 +12702,14 @@
 @itemx -mno-interlink-mips16
 @opindex minterlink-mips16
 @opindex mno-interlink-mips16
-Require (do not require) that non-MIPS16 code be link-compatible with
-MIPS16 code.
+Require (do not require) that non-MIPS16/non-microMIPS code be link-compatible
+with MIPS16/microMIPS code.
 
-For example, non-MIPS16 code cannot jump directly to MIPS16 code;
+For example, non-MIPS16/non-microMIPS code cannot jump directly to
+MIPS16/microMIPS code;
 it must either use a call or an indirect jump.  @option{-minterlink-mips16}
 therefore disables direct jumps unless GCC knows that the target of the
-jump is not MIPS16.
+jump is not MIPS16/non microMIPS.
 
 @item -mabi=32
 @itemx -mabi=o64
@@ -12908,12 +12912,29 @@
 Use (do not use) the MIPS-3D ASE@.  @xref{MIPS-3D Built-in Functions}.
 The option @option{-mips3d} implies @option{-mpaired-single}.
 
+@item -mmicromips
+@itemx -mno-micromips
+@opindex mmicromips
+@opindex mno-mmicromips
+Generate (do not generate) microMIPS code.  If GCC is targetting a
+MIPS32 or MIPS64 architecture, it will make use of the microMIPS ASE@.
+
+MicroMIPS code generation can also be controlled on a per-function basis
+by means of @code{micromips} and @code{nomicromips} attributes.
+@xref{Function Attributes}, for more information.
+
 @item -mmt
 @itemx -mno-mt
 @opindex mmt
 @opindex mno-mt
 Use (do not use) MT Multithreading instructions.
 
+@item -mmcu
+@itemx -mno-mcu
+@opindex mmcu
+@opindex mno-mcu
+Use (do not use) the MIPS MCU ASE instructions.
+
 @item -mlong64
 @opindex mlong64
 Force @code{long} types to be 64 bits wide.  See @option{-mlong32} for
@@ -13109,6 +13130,16 @@
 This option has no effect on abicalls code.  The default is
 @option{-mno-long-calls}.
 
+@item -mjals
+@itemx -mno-jals
+@opindex mjals
+@opindex mno-jals
+Generate (do not generate) the @code{jals} instruction for microMIPS
+by recognizing that the branch delay slot instruction can be 16 bits.
+This implies that the funciton call cannot switch the current mode
+during the linking stage, because we don't have the @code{jalxs}
+instruction that supports 16-bit branch delay slot instructions.
+
 @item -mmad
 @itemx -mno-mad
 @opindex mmad
@@ -13768,9 +13799,9 @@
 instruction scheduling parameters for machine type @var{cpu_type}.
 Supported values for @var{cpu_type} are @samp{401}, @samp{403},
 @samp{405}, @samp{405fp}, @samp{440}, @samp{440fp}, @samp{464}, @samp{464fp},
-@samp{505}, @samp{601}, @samp{602}, @samp{603}, @samp{603e}, @samp{604},
-@samp{604e}, @samp{620}, @samp{630}, @samp{740}, @samp{7400},
-@samp{7450}, @samp{750}, @samp{801}, @samp{821}, @samp{823},
+@samp{476}, @samp{476fp}, @samp{505}, @samp{601}, @samp{602}, @samp{603},
+@samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{630}, @samp{740},
+@samp{7400}, @samp{7450}, @samp{750}, @samp{801}, @samp{821}, @samp{823},
 @samp{860}, @samp{970}, @samp{8540}, @samp{e300c2}, @samp{e300c3},
 @samp{e500mc}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
 @samp{power}, @samp{power2}, @samp{power3}, @samp{power4},
@@ -14108,7 +14139,7 @@
 @opindex mmulhw
 @opindex mno-mulhw
 Generate code that uses (does not use) the half-word multiply and
-multiply-accumulate instructions on the IBM 405, 440 and 464 processors.
+multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors.
 These instructions are generated by default when targetting those
 processors.
 
@@ -14117,7 +14148,7 @@
 @opindex mdlmzb
 @opindex mno-dlmzb
 Generate code that uses (does not use) the string-search @samp{dlmzb}
-instruction on the IBM 405, 440 and 464 processors.  This instruction is
+instruction on the IBM 405, 440, 464 and 476 processors.  This instruction is
 generated by default when targetting those processors.
 
 @item -mno-bit-align
@@ -14403,6 +14434,13 @@
 in the @samp{.data} section, and all uninitialized data in the
 @samp{.bss} section.
 
+@item -mblock-move-inline-limit=@var{num}
+@opindex mblock-move-inline-limit
+Inline all block moves (such as calls to @code{memcpy} or structure
+copies) less than or equal to @var{num} bytes.  The minimum value for
+@var{num} is 32 bytes on 32-bit targets and 64 bytes on 64-bit
+targets.  The default value is target-specific.
+
 @item -G @var{num}
 @opindex G
 @cindex smaller data references (PowerPC)
@@ -14978,6 +15016,11 @@
 This option is only meaningful when @option{-mno-pt-fixed} is in effect.
 It will then prevent cross-basic-block cse, hoisting and most scheduling
 of symbol loads.  The default is @option{-mno-invalid-symbols}.
+
+@item -mfdpic
+@opindex fdpic
+Generate code using the FDPIC ABI for uClinux, as documented at
+@w{@uref{http://www.codesourcery.com/public/docs/sh-fdpic/sh-fdpic-abi.txt}}.
 @end table
 
 @node SPARC Options
diff -Naur a/src/gcc/doc/md.texi b/src/gcc/doc/md.texi
--- a/src/gcc/doc/md.texi	2009-10-12 21:15:43.000000000 +0300
+++ b/src/gcc/doc/md.texi	2010-03-30 10:32:30.000000000 +0300
@@ -2574,6 +2574,9 @@
 
 @item R
 An address that can be used in a non-macro load or store.
+
+@item YC
+For MIPS, it is the same as the constraint @code{R}.  For microMIPS, it matches an address within a 12-bit offset that can be used for microMIPS @code{ll}, @code{sc}, etc.
 @end table
 
 @item Motorola 680x0---@file{config/m68k/constraints.md}
diff -Naur a/src/gcc/doc/tm.texi b/src/gcc/doc/tm.texi
--- a/src/gcc/doc/tm.texi	2009-10-12 21:15:43.000000000 +0300
+++ b/src/gcc/doc/tm.texi	2010-04-10 10:19:14.000000000 +0300
@@ -6881,8 +6881,9 @@
 @end defmac
 
 @defmac PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
-Define this macro if the register defined by
-@code{PIC_OFFSET_TABLE_REGNUM} is clobbered by calls.  Do not define
+A C expression that is nonzero if the register defined by
+@code{PIC_OFFSET_TABLE_REGNUM} is clobbered by calls.  If not defined,
+the default is zero.  Do not define
 this macro if @code{PIC_OFFSET_TABLE_REGNUM} is not defined.
 @end defmac
 
@@ -8144,6 +8145,22 @@
 to registers using alternate names.
 @end defmac
 
+@defmac OVERLAPPING_REGISTER_NAMES
+If defined, a C initializer for an array of structures containing a
+name, a register number and a count of the number of consecutive
+machine registers the name overlaps.  This macro defines additional
+names for hard registers, thus allowing the @code{asm} option in
+declarations to refer to registers using alternate names.  Unlike
+@code{ADDITIONAL_REGISTER_NAMES}, this macro should be used when the
+register name implies multiple underlying registers.
+
+This macro should be used when it is important that a clobber in an
+@code{asm} statement clobbers all the underlying values implied by the
+register name.  For example, on ARM, clobbering the double-precision
+VFP register ``d0'' implies clobbering both single-precision registers
+``s0'' and ``s1''.
+@end defmac
+
 @defmac ASM_OUTPUT_OPCODE (@var{stream}, @var{ptr})
 Define this macro if you are using an unusual assembler that
 requires different names for the machine instructions.
@@ -8193,6 +8210,19 @@
 If this macro is not defined, it is equivalent to a null statement.
 @end defmac
 
+@deftypefn {Target Hook} void TARGET_ASM_FINAL_POSTSCAN_INSN (FILE *@var{FILE}, rtx @var{insn}, rtx *@var{opvec}, int @var{noperands})
+If defined, this target hook is a function which is executed just after the
+output of assembler code for @var{insn}, to change the mode of the assembler
+if necessary.
+
+Here the argument @var{opvec} is the vector containing the operands
+extracted from @var{insn}, and @var{noperands} is the number of
+elements of the vector which contain meaningful data for this insn.
+The contents of this vector are what was used to convert the insn
+template into assembler code, so you can change the assembler mode
+by checking the contents of the vector.
+@end deftypefn
+
 @defmac PRINT_OPERAND (@var{stream}, @var{x}, @var{code})
 A C compound statement to output to stdio stream @var{stream} the
 assembler syntax for an instruction operand @var{x}.  @var{x} is an
diff -Naur a/src/gcc/dwarf2out.c b/src/gcc/dwarf2out.c
--- a/src/gcc/dwarf2out.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/dwarf2out.c	2010-04-08 10:44:38.000000000 +0300
@@ -103,6 +103,9 @@
 # endif
 #endif
 
+#define NEED_UNWIND_TABLES \
+  (flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS))
+
 /* Map register numbers held in the call frame info that gcc has
    collected using DWARF_FRAME_REGNUM to those that should be output in
    .debug_frame and .eh_frame.  */
@@ -126,9 +129,7 @@
 	  || write_symbols == VMS_AND_DWARF2_DEBUG
 	  || DWARF2_FRAME_INFO || saved_do_cfi_asm
 #ifdef DWARF2_UNWIND_INFO
-	  || (DWARF2_UNWIND_INFO
-	      && (flag_unwind_tables
-		  || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)))
+	  || (DWARF2_UNWIND_INFO && NEED_UNWIND_TABLES)
 #endif
 	  );
 }
@@ -145,7 +146,18 @@
 #endif
   if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
     return false;
-  if (saved_do_cfi_asm || !eh_personality_libfunc)
+  if (saved_do_cfi_asm)
+    return true;
+  if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE)
+    {
+#ifdef TARGET_UNWIND_INFO
+      return false;
+#else
+      if (!NEED_UNWIND_TABLES)
+	return false;
+#endif
+    }
+  if (!eh_personality_libfunc)
     return true;
   if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
     return false;
@@ -3239,8 +3251,7 @@
   /* ??? current_function_func_begin_label is also used by except.c
      for call-site information.  We must emit this label if it might
      be used.  */
-  if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS)
-      && ! dwarf2out_do_frame ())
+  if (! NEED_UNWIND_TABLES && ! dwarf2out_do_frame ())
     return;
 #else
   if (! dwarf2out_do_frame ())
@@ -3398,7 +3409,7 @@
 
 #ifndef TARGET_UNWIND_INFO
   /* Output another copy for the unwinder.  */
-  if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
+  if (NEED_UNWIND_TABLES)
     output_call_frame_info (1);
 #endif
 }
@@ -4589,6 +4600,7 @@
 
 static void dwarf2out_init (const char *);
 static void dwarf2out_finish (const char *);
+static void dwarf2out_assembly_start (void);
 static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
 static void dwarf2out_start_source_file (unsigned, const char *);
@@ -4612,6 +4624,7 @@
 {
   dwarf2out_init,
   dwarf2out_finish,
+  dwarf2out_assembly_start,
   dwarf2out_define,
   dwarf2out_undef,
   dwarf2out_start_source_file,
@@ -16185,6 +16198,27 @@
       switch_to_section (cold_text_section);
       ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
     }
+
+}
+
+/* Called before cgraph_optimize starts outputtting functions, variables
+   and toplevel asms into assembly.  */
+
+static void
+dwarf2out_assembly_start (void)
+{
+  if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE && dwarf2out_do_cfi_asm ())
+    {
+#ifdef TARGET_UNWIND_INFO
+      /* We're only ever interested in .debug_frame.  */
+      fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
+#else
+      /* GAS defaults to emitting .eh_frame only, and .debug_frame is not
+	 wanted in case that the former one is present.  */
+      if (! NEED_UNWIND_TABLES)
+	fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
+#endif
+    }
 }
 
 /* A helper function for dwarf2out_finish called through
diff -Naur a/src/gcc/final.c b/src/gcc/final.c
--- a/src/gcc/final.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/final.c	2010-03-30 10:39:46.000000000 +0300
@@ -2228,6 +2228,10 @@
 #endif
 	      }
 
+	    if (targetm.asm_out.final_postscan_insn)
+	      targetm.asm_out.final_postscan_insn (file, insn, ops,
+						   insn_noperands);
+
 	    this_is_asm_operands = 0;
 	    break;
 	  }
@@ -2630,6 +2634,12 @@
 	/* Output assembler code from the template.  */
 	output_asm_insn (templ, recog_data.operand);
 
+	/* Some target machines need to postscan each insn after
+	   it is output.  */
+	if (targetm.asm_out.final_postscan_insn)
+	  targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand,
+					       recog_data.n_operands);
+
 	/* If necessary, report the effect that the instruction has on
 	   the unwind info.   We've already done this for delay slots
 	   and call instructions.  */
diff -Naur a/src/gcc/fortran/Make-lang.in b/src/gcc/fortran/Make-lang.in
--- a/src/gcc/fortran/Make-lang.in	2009-10-12 21:20:32.000000000 +0300
+++ b/src/gcc/fortran/Make-lang.in	2010-03-30 10:38:52.000000000 +0300
@@ -26,7 +26,7 @@
 #
 # foo.all.cross, foo.start.encap, foo.rest.encap,
 # foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
-# foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
 # foo.mostlyclean, foo.clean, foo.distclean,
 # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
 #
@@ -118,7 +118,27 @@
 
 fortran.info: doc/gfortran.info doc/gfc-internals.info
 fortran.dvi: doc/gfortran.dvi doc/gfc-internals.dvi
-fortran.html: $(build_htmldir)/gfortran/index.html
+
+F95_HTMLFILES = $(build_htmldir)/gfortran
+
+fortran.html: $(F95_HTMLFILES)/index.html
+
+fortran.install-html: $(F95_HTMLFILES)
+	@$(NORMAL_INSTALL)
+	test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
+	@list='$(F95_HTMLFILES)'; for p in $$list; do \
+	  if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \
+	  f=$(html__strip_dir) \
+	  if test -d "$$d$$p"; then \
+	    echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
+	    echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
+	  else \
+	    echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
+	  fi; \
+	done
 
 F95_PDFFILES = doc/gfortran.pdf
 
diff -Naur a/src/gcc/gthr-win32.h b/src/gcc/gthr-win32.h
--- a/src/gcc/gthr-win32.h	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/gthr-win32.h	2010-03-30 10:39:46.000000000 +0300
@@ -67,7 +67,9 @@
 
 #define __GTHREADS 1
 
+#ifndef __MINGW32CE__
 #include <errno.h>
+#endif
 #ifdef __MINGW32__
 #include <_mingw.h>
 #endif
@@ -535,7 +537,9 @@
 #else /* ! __GTHREAD_HIDE_WIN32API */
 
 #include <windows.h>
+#ifndef __MINGW32CE__
 #include <errno.h>
+#endif
 
 static inline int
 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
@@ -543,7 +547,11 @@
   if (! __gthread_active_p ())
     return -1;
   else if (__once == NULL || __func == NULL)
+#ifdef __MINGW32CE__
+    return -1;
+#else
     return EINVAL;
+#endif
 
   if (! __once->done)
     {
diff -Naur a/src/gcc/ifcvt.c b/src/gcc/ifcvt.c
--- a/src/gcc/ifcvt.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/ifcvt.c	2010-04-14 10:28:39.000000000 +0300
@@ -390,7 +390,11 @@
   rtx false_expr;		/* test for then block insns */
   rtx true_prob_val;		/* probability of else block */
   rtx false_prob_val;		/* probability of then block */
-  int n_insns;
+  rtx then_last_head = NULL_RTX;	/* Last match at the head of THEN */
+  rtx else_last_head = NULL_RTX;	/* Last match at the head of ELSE */
+  rtx then_first_tail = NULL_RTX;	/* First match at the tail of THEN */
+  rtx else_first_tail = NULL_RTX;	/* First match at the tail of ELSE */
+  int then_n_insns, else_n_insns, n_insns;
   enum rtx_code false_code;
 
   /* If test is comprised of && or || elements, and we've failed at handling
@@ -423,15 +427,80 @@
      number of insns and see if it is small enough to convert.  */
   then_start = first_active_insn (then_bb);
   then_end = last_active_insn (then_bb, TRUE);
-  n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
+  then_n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
+  n_insns = then_n_insns;
   max = MAX_CONDITIONAL_EXECUTE;
 
   if (else_bb)
     {
+      int n_matching;
+
       max *= 2;
       else_start = first_active_insn (else_bb);
       else_end = last_active_insn (else_bb, TRUE);
-      n_insns += ce_info->num_else_insns = count_bb_insns (else_bb);
+      else_n_insns = ce_info->num_else_insns = count_bb_insns (else_bb);
+      n_insns += else_n_insns;
+
+      /* Look for matching sequences at the head and tail of the two blocks,
+	 and limit the range of insns to be converted if possible.  */
+      n_matching = flow_find_cross_jump (0, then_bb, else_bb,
+					 &then_first_tail, &else_first_tail);
+      if (then_first_tail == BB_HEAD (then_bb))
+	then_start = then_end = NULL_RTX;
+      if (else_first_tail == BB_HEAD (else_bb))
+	else_start = else_end = NULL_RTX;
+
+      if (n_matching > 0)
+	{
+	  if (then_end)
+	    then_end = prev_active_insn (then_first_tail);
+	  if (else_end)
+	    else_end = prev_active_insn (else_first_tail);
+	  n_insns -= 2 * n_matching;
+	}
+
+      if (then_start && else_start)
+	{
+	  int longest_match = MIN (then_n_insns - n_matching,
+				   else_n_insns - n_matching);
+	  n_matching
+	    = flow_find_head_matching_sequence (0, then_bb, else_bb,
+						&then_last_head,
+						&else_last_head,
+						longest_match);
+      
+	  if (then_last_head == then_end)
+	    then_start = then_end = NULL_RTX;
+	  if (else_last_head == else_end)
+	    else_start = else_end = NULL_RTX;
+
+	  if (n_matching > 0)
+	    {
+	      rtx insn;
+
+	      if (then_start)
+		then_start = next_active_insn (then_last_head);
+	      if (else_start)
+		else_start = next_active_insn (else_last_head);
+	      n_insns -= 2 * n_matching;
+
+	      /* We won't pass the insns in the head sequence to
+		 cond_exec_process_insns, so we need to test them here
+		 to make sure that they don't clobber the condition.  */
+	      insn = BB_HEAD (then_bb);
+	      for (;;)
+		{
+		  if (!LABEL_P (insn) && !NOTE_P (insn))
+		    {
+		      if (modified_in_p (test_expr, insn))
+			return FALSE;
+		    }
+		  if (insn == then_last_head)
+		    break;
+		  insn = NEXT_INSN (insn);
+		}
+	    }
+	}
     }
 
   if (n_insns > max)
@@ -575,7 +644,18 @@
     fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
 	     n_insns, (n_insns == 1) ? " was" : "s were");
 
-  /* Merge the blocks!  */
+  /* Merge the blocks!  If we had matching sequences, make sure to delete one
+     copy at the appropriate location first.  */
+  if (then_first_tail)
+    {
+      rtx from = then_first_tail;
+      if (!INSN_P (from))
+	from = next_active_insn (from);
+      delete_insn_chain (from, BB_END (then_bb), false);
+    }
+  if (else_last_head)
+    delete_insn_chain (first_active_insn (else_bb), else_last_head, false);
+
   merge_if_block (ce_info);
   cond_exec_changed_p = TRUE;
   return TRUE;
@@ -2866,6 +2946,152 @@
   return FALSE;
 }
 
+/* Try to move identical code from the THEN and ELSE blocks backwards across a
+   conditional jump into the IF block.  CE_INFO describes the structure we
+   found.  */
+
+static bool
+move_across_if (struct ce_if_block * ce_info)
+{
+  basic_block test_bb = ce_info->test_bb;
+  basic_block then_bb = ce_info->then_bb;
+  basic_block else_bb = ce_info->else_bb;
+  edge cur_edge;
+  edge_iterator ei;
+  rtx test_expr;
+  rtx then_start, else_start;
+  rtx then_last_head, else_last_head;
+  int n_matching;
+
+  if (!else_bb)
+    return false;
+
+  ce_info->last_test_bb = test_bb;
+
+  /* We only ever should get here after reload.  */
+  gcc_assert (reload_completed);
+
+  /* The THEN and ELSE blocks must have exactly one predecessor.  */
+  if (EDGE_COUNT (then_bb->preds) != 1 || EDGE_COUNT (else_bb->preds) != 1)
+    return FALSE;
+
+  if (else_bb == EXIT_BLOCK_PTR || then_bb == EXIT_BLOCK_PTR)
+    return FALSE;
+
+  /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
+  FOR_EACH_EDGE (cur_edge, ei, then_bb->preds)
+    {
+      if (cur_edge->flags & EDGE_COMPLEX)
+	return FALSE;
+    }
+
+  FOR_EACH_EDGE (cur_edge, ei, else_bb->preds)
+    {
+      if (cur_edge->flags & EDGE_COMPLEX)
+	return FALSE;
+    }
+
+  num_possible_if_blocks++;
+
+  if (dump_file)
+    {
+      fprintf (dump_file,
+	       "\nIF-THEN%s block found, pass %d, start block %d "
+	       "[insn %d], then %d [%d]",
+	       (else_bb) ? "-ELSE" : "",
+	       ce_info->pass,
+	       test_bb->index,
+	       BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
+	       then_bb->index,
+	       BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
+
+      fprintf (dump_file, ", else %d [%d]",
+	       else_bb->index,
+	       BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
+
+      fputc ('\n', dump_file);
+    }
+
+  /* Do the real work.  */
+
+  ce_info->else_bb = else_bb;
+  /* Find the conditional jump to the ELSE or JOIN part, and isolate
+     the test.  */
+  test_expr = cond_exec_get_condition (BB_END (test_bb));
+  if (! test_expr)
+    return FALSE;
+
+  /* We only have to avoid clobbering the expression; try to reduce it
+     to a single reg.  */
+  if ((GET_RTX_CLASS (GET_CODE (test_expr)) == RTX_COMM_COMPARE
+       || GET_RTX_CLASS (GET_CODE (test_expr)) == RTX_COMPARE)
+      && REG_P (XEXP (test_expr, 0))
+      && CONSTANT_P (XEXP (test_expr, 1)))
+    test_expr = XEXP (test_expr, 0);
+
+  /* If the conditional jump is more than just a conditional jump,
+     then we can not do conditional execution conversion on this block.  */
+  if (! onlyjump_p (BB_END (test_bb))
+      || GET_CODE (PATTERN (BB_END (test_bb))) == PARALLEL)
+    return FALSE;
+
+  /* Collect the bounds of where we're to search, skipping any labels, jumps
+     and notes at the beginning and end of the block.  Then count the total
+     number of insns and see if it is small enough to convert.  */
+  then_start = first_active_insn (then_bb);
+  else_start = first_active_insn (else_bb);
+
+  if (then_start == NULL || else_start == NULL)
+    return FALSE;
+  
+  n_matching
+    = flow_find_head_matching_sequence (0, then_bb, else_bb,
+					&then_last_head,
+					&else_last_head, 0);
+      
+  if (n_matching > 0)
+    {
+      rtx then_insn, else_insn;
+      rtx last_then = NULL_RTX, last_else = NULL_RTX;
+
+      then_insn = then_start;
+      else_insn = else_start;
+      for (;;)
+	{
+	  if (modified_in_p (test_expr, then_insn))
+	    break;
+
+	  if (then_insn == BB_END (then_bb)
+	      && (find_reg_note (then_insn, REG_EH_REGION, 0)
+		  || control_flow_insn_p (then_insn)))
+	    break;
+	  
+	  last_then = then_insn;
+	  last_else = else_insn;
+
+	  if (then_insn == then_last_head)
+	    break;
+	  then_insn = next_active_insn (then_insn);
+	  else_insn = next_active_insn (else_insn);
+	}
+      if (last_then == NULL_RTX)
+	return FALSE;
+
+      df_set_bb_dirty (test_bb);
+      df_set_bb_dirty (then_bb);
+      df_set_bb_dirty (else_bb);
+      reorder_insns (then_start, last_then,
+		     PREV_INSN (BB_END (test_bb)));
+      delete_insn_chain (else_start, last_else, false);
+
+      num_true_changes++;
+      num_updated_if_blocks++;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 
 /* Merge the blocks and mark for local life update.  */
 
@@ -3043,6 +3269,9 @@
       && cond_exec_find_if_block (&ce_info))
     goto success;
 
+  if (reload_completed && move_across_if (&ce_info))
+    goto success;
+
   if (HAVE_trap && HAVE_conditional_trap
       && find_cond_trap (test_bb, then_edge, else_edge))
     goto success;
diff -Naur a/src/gcc/input.h b/src/gcc/input.h
--- a/src/gcc/input.h	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/input.h	2010-03-30 10:39:46.000000000 +0300
@@ -1,6 +1,6 @@
 /* Declarations for variables relating to reading the source file.
    Used by parsers, lexical analyzers, and error message routines.
-   Copyright (C) 1993, 1997, 1998, 2000, 2003, 2004, 2007, 2008
+   Copyright (C) 1993, 1997, 1998, 2000, 2003, 2004, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -30,7 +30,12 @@
 #define UNKNOWN_LOCATION ((source_location) 0)
 
 /* The location for declarations in "<built-in>" */
-#define BUILTINS_LOCATION ((source_location) 2)
+#define BUILTINS_LOCATION ((source_location) 1)
+
+/* line-map.c reserves RESERVED_LOCATION_COUNT to the user.  Ensure
+   both UNKNOWN_LOCATION and BUILTINS_LOCATION fit into that.  */
+extern char builtins_location_check[(BUILTINS_LOCATION
+				     < RESERVED_LOCATION_COUNT) ? 1 : -1];
 
 typedef struct GTY (())
 {
diff -Naur a/src/gcc/ira.c b/src/gcc/ira.c
--- a/src/gcc/ira.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/ira.c	2010-04-02 10:28:17.000000000 +0300
@@ -1387,12 +1387,6 @@
 static void
 setup_eliminable_regset (void)
 {
-  /* Like regs_ever_live, but 1 if a reg is set or clobbered from an
-     asm.  Unlike regs_ever_live, elements of this array corresponding
-     to eliminable regs (like the frame pointer) are set if an asm
-     sets them.  */
-  char *regs_asm_clobbered
-    = (char *) alloca (FIRST_PSEUDO_REGISTER * sizeof (char));
 #ifdef ELIMINABLE_REGS
   int i;
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
@@ -3057,6 +3051,9 @@
 
   timevar_push (TV_IRA);
 
+  if (flag_caller_saves)
+    init_caller_save ();
+
   if (flag_ira_verbose < 10)
     {
       internal_flag_ira_verbose = flag_ira_verbose;
diff -Naur a/src/gcc/ira-costs.c b/src/gcc/ira-costs.c
--- a/src/gcc/ira-costs.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/ira-costs.c	2010-04-09 10:32:04.000000000 +0300
@@ -209,6 +209,14 @@
       int alt_fail = 0;
       int alt_cost = 0, op_cost_add;
 
+      if (!recog_data.alternative_enabled_p[alt])
+	{
+	  for (i = 0; i < recog_data.n_operands; i++)
+	    constraints[i] = skip_alternative (constraints[i]);
+
+	  continue;
+	}
+
       for (i = 0; i < n_ops; i++)
 	{
 	  unsigned char c;
diff -Naur a/src/gcc/java/Make-lang.in b/src/gcc/java/Make-lang.in
--- a/src/gcc/java/Make-lang.in	2009-10-12 21:15:49.000000000 +0300
+++ b/src/gcc/java/Make-lang.in	2010-03-30 10:32:36.000000000 +0300
@@ -28,7 +28,7 @@
 #
 # foo.all.cross, foo.start.encap, foo.rest.encap,
 # foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
-# foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
 # foo.mostlyclean, foo.clean, foo.distclean,
 # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
 #
@@ -137,7 +137,9 @@
 
 java.pdf: $(JAVA_PDFFILES)
 
-java.html: $(build_htmldir)/java/index.html
+JAVA_HTMLFILES = $(build_htmldir)/java
+
+java.html: $(JAVA_HTMLFILES)/index.html
 
 JAVA_MANFILES = doc/gcj.1 doc/jcf-dump.1 doc/gij.1 \
                 doc/jv-convert.1 doc/grmic.1 \
@@ -203,6 +205,22 @@
 	  $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/$$f"; \
 	done
 
+java.install-html: $(JAVA_HTMLFILES)
+	@$(NORMAL_INSTALL)
+	test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
+	@list='$(JAVA_HTMLFILES)'; for p in $$list; do \
+	  if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \
+	  f=$(html__strip_dir) \
+	  if test -d "$$d$$p"; then \
+	    echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
+	    echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
+	  else \
+	    echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
+	    $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
+	  fi; \
+	done
 #
 # Clean hooks:
 # A lot of the ancillary files are deleted by the main makefile.
diff -Naur a/src/gcc/Makefile.in b/src/gcc/Makefile.in
--- a/src/gcc/Makefile.in	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/Makefile.in	2010-03-30 10:39:47.000000000 +0300
@@ -2084,7 +2084,7 @@
    all-tree.def $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
    $(TOPLEV_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
    $(REAL_H) gt-tree.h tree-iterator.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
-   $(OBSTACK_H) pointer-set.h fixed-value.h
+   $(OBSTACK_H) pointer-set.h fixed-value.h intl.h
 tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) langhooks.h $(TOPLEV_H) $(SPLAY_TREE_H) $(TREE_DUMP_H) \
    tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h
@@ -3955,8 +3955,7 @@
 
 # List the directories or single hmtl files which are installed by
 # install-html. The lang.html file triggers language fragments to build
-# html documentation. Installing language fragment documentation is not
-# yet supported.
+# html documentation.
 HTMLS_INSTALL=$(build_htmldir)/cpp $(build_htmldir)/gcc \
        $(build_htmldir)/gccinstall $(build_htmldir)/gccint \
        $(build_htmldir)/cppinternals
@@ -4259,7 +4258,7 @@
 
 html__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
 
-install-html: $(HTMLS_BUILD)
+install-html: $(HTMLS_BUILD) lang.install-html
 	@$(NORMAL_INSTALL)
 	test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
 	@list='$(HTMLS_INSTALL)'; for p in $$list; do \
diff -Naur a/src/gcc/objc/Make-lang.in b/src/gcc/objc/Make-lang.in
--- a/src/gcc/objc/Make-lang.in	2009-10-12 21:15:53.000000000 +0300
+++ b/src/gcc/objc/Make-lang.in	2010-03-30 10:32:42.000000000 +0300
@@ -24,7 +24,7 @@
 #
 # foo.all.cross, foo.start.encap, foo.rest.encap,
 # foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
-# foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
 # foo.mostlyclean, foo.clean, foo.distclean,
 # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
 #
@@ -95,6 +95,7 @@
 objc.pdf:
 objc.install-pdf:
 objc.html:
+objc.install-html:
 objc.man:
 objc.srcinfo:
 objc.srcman:
diff -Naur a/src/gcc/objcp/Make-lang.in b/src/gcc/objcp/Make-lang.in
--- a/src/gcc/objcp/Make-lang.in	2009-10-12 21:19:56.000000000 +0300
+++ b/src/gcc/objcp/Make-lang.in	2010-03-30 10:38:10.000000000 +0300
@@ -24,7 +24,7 @@
 #
 # foo.all.cross, foo.start.encap, foo.rest.encap,
 # foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
-# foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
 # foo.mostlyclean, foo.clean, foo.distclean,
 # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
 #
@@ -103,6 +103,7 @@
 obj-c++.pdf:
 obj-c++.install-pdf:
 obj-c++.html:
+obj-c++.install-html:
 obj-c++.srcinfo:
 obj-c++.srcextra:
 obj-c++.man:
diff -Naur a/src/gcc/opts.c b/src/gcc/opts.c
--- a/src/gcc/opts.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/opts.c	2010-03-30 10:39:47.000000000 +0300
@@ -892,7 +892,8 @@
   flag_caller_saves = opt2;
   flag_peephole2 = opt2;
 #ifdef INSN_SCHEDULING
-  flag_schedule_insns = opt2;
+  /* Only run the pre-regalloc scheduling pass if optimizing for speed.  */
+  flag_schedule_insns = opt2 && ! optimize_size;
   flag_schedule_insns_after_reload = opt2;
 #endif
   flag_regmove = opt2;
diff -Naur a/src/gcc/output.h b/src/gcc/output.h
--- a/src/gcc/output.h	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/output.h	2010-04-10 10:19:16.000000000 +0300
@@ -169,6 +169,11 @@
    Prefixes such as % are optional.  */
 extern int decode_reg_name (const char *);
 
+/* Similar to decode_reg_name, but takes an extra parameter that is a
+   pointer to the number of (internal) registers described by the
+   external name.  */
+extern int decode_reg_name_and_count (const char *, int *);
+
 extern void assemble_alias (tree, tree);
 
 extern void default_assemble_visibility (tree, int);
diff -Naur a/src/gcc/passes.c b/src/gcc/passes.c
--- a/src/gcc/passes.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/passes.c	2010-03-30 10:39:47.000000000 +0300
@@ -793,6 +793,7 @@
 	  NEXT_PASS (pass_leaf_regs);
 	  NEXT_PASS (pass_split_before_sched2);
 	  NEXT_PASS (pass_sched2);
+	  NEXT_PASS (pass_peephole2);
 	  NEXT_PASS (pass_stack_regs);
 	    {
 	      struct opt_pass **p = &pass_stack_regs.pass.sub;
diff -Naur a/src/gcc/reginfo.c b/src/gcc/reginfo.c
--- a/src/gcc/reginfo.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/reginfo.c	2010-04-10 10:19:18.000000000 +0300
@@ -559,10 +559,9 @@
       else if (i == ARG_POINTER_REGNUM && fixed_regs[i])
 	;
 #endif
-#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
-      else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
+      else if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+	       && i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
 	;
-#endif
       else if (CALL_REALLY_USED_REGNO_P (i))
         {
 	  SET_HARD_REG_BIT (regs_invalidated_by_call, i);
@@ -798,36 +797,41 @@
 fix_register (const char *name, int fixed, int call_used)
 {
   int i;
+  int reg, nregs;
 
   /* Decode the name and update the primary form of
      the register info.  */
 
-  if ((i = decode_reg_name (name)) >= 0)
+  if ((reg = decode_reg_name_and_count (name, &nregs)) >= 0)
     {
-      if ((i == STACK_POINTER_REGNUM
+      gcc_assert (nregs >= 1);
+      for (i = reg; i < reg + nregs; i++)
+	{
+	  if ((i == STACK_POINTER_REGNUM
 #ifdef HARD_FRAME_POINTER_REGNUM
-	   || i == HARD_FRAME_POINTER_REGNUM
+	       || i == HARD_FRAME_POINTER_REGNUM
 #else
-	   || i == FRAME_POINTER_REGNUM
+	       || i == FRAME_POINTER_REGNUM
 #endif
-	   )
-	  && (fixed == 0 || call_used == 0))
-	{
-	  static const char * const what_option[2][2] = {
-	    { "call-saved", "call-used" },
-	    { "no-such-option", "fixed" }};
-
-	  error ("can't use '%s' as a %s register", name,
-		 what_option[fixed][call_used]);
-	}
-      else
-	{
-	  fixed_regs[i] = fixed;
-	  call_used_regs[i] = call_used;
+	       )
+	      && (fixed == 0 || call_used == 0))
+	    {
+	      static const char * const what_option[2][2] = {
+		{ "call-saved", "call-used" },
+		{ "no-such-option", "fixed" }};
+
+	      error ("can't use '%s' as a %s register", name,
+		     what_option[fixed][call_used]);
+	    }
+	  else
+	    {
+	      fixed_regs[i] = fixed;
+	      call_used_regs[i] = call_used;
 #ifdef CALL_REALLY_USED_REGISTERS
-	  if (fixed == 0)
-	    call_really_used_regs[i] = call_used;
+	      if (fixed == 0)
+		call_really_used_regs[i] = call_used;
 #endif
+	    }
 	}
     }
   else
diff -Naur a/src/gcc/regmove.c b/src/gcc/regmove.c
--- a/src/gcc/regmove.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/regmove.c	2010-04-14 10:28:39.000000000 +0300
@@ -855,7 +855,7 @@
 	break;
 
       /* If we have passed a call instruction, and the
-         pseudo-reg SRC is not already live across a call,
+         pseudo-reg DST is not already live across a call,
          then don't perform the optimization.  */
       /* reg_set_p is overly conservative for CALL_INSNS, thinks that all
 	 hard regs are clobbered.  Thus, we only use it for src for
@@ -868,11 +868,11 @@
 	      freq_calls += REG_FREQ_FROM_BB  (BLOCK_FOR_INSN (p));
 	    }
 
-	  if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
+	  if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0)
 	    break;
 
-	  if (call_used_regs [REGNO (dst)]
-	      || find_reg_fusage (p, CLOBBER, dst))
+	  if (call_used_regs [REGNO (src)]
+	      || find_reg_fusage (p, CLOBBER, src))
 	    break;
 	}
       else if (reg_set_p (src, PATTERN (p)))
diff -Naur a/src/gcc/reload.h b/src/gcc/reload.h
--- a/src/gcc/reload.h	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/reload.h	2010-04-02 10:28:17.000000000 +0300
@@ -349,6 +349,9 @@
 /* Deallocate the reload register used by reload number R.  */
 extern void deallocate_reload_reg (int r);
 
+/* True if caller-save has been reinitialized.  */
+extern bool caller_save_initialized_p;
+
 /* Functions in caller-save.c:  */
 
 /* Initialize for caller-save.  */
diff -Naur a/src/gcc/rtlanal.c b/src/gcc/rtlanal.c
--- a/src/gcc/rtlanal.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/rtlanal.c	2010-03-30 10:39:46.000000000 +0300
@@ -132,13 +132,11 @@
 	  /* The arg pointer varies if it is not a fixed register.  */
 	  || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM]))
 	return 0;
-#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
       /* ??? When call-clobbered, the value is stable modulo the restore
 	 that must happen after a call.  This currently screws up local-alloc
 	 into believing that the restore is not needed.  */
-      if (x == pic_offset_table_rtx)
+      if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED && x == pic_offset_table_rtx)
 	return 0;
-#endif
       return 1;
 
     case ASM_OPERANDS:
@@ -211,14 +209,11 @@
 	  || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM]))
 	return 0;
       if (x == pic_offset_table_rtx
-#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
 	  /* ??? When call-clobbered, the value is stable modulo the restore
 	     that must happen after a call.  This currently screws up
 	     local-alloc into believing that the restore is not needed, so we
 	     must return 0 only if we are called from alias analysis.  */
-	  && for_alias
-#endif
-	  )
+	  && (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED || for_alias))
 	return 0;
       return 1;
 
diff -Naur a/src/gcc/sdbout.c b/src/gcc/sdbout.c
--- a/src/gcc/sdbout.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/sdbout.c	2010-03-30 10:39:47.000000000 +0300
@@ -307,6 +307,7 @@
 {
   sdbout_init,			         /* init */
   sdbout_finish,		         /* finish */
+  debug_nothing_void,			 /* assembly_start */
   debug_nothing_int_charstar,	         /* define */
   debug_nothing_int_charstar,	         /* undef */
   sdbout_start_source_file,	         /* start_source_file */
diff -Naur a/src/gcc/stmt.c b/src/gcc/stmt.c
--- a/src/gcc/stmt.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/stmt.c	2010-04-10 10:19:18.000000000 +0300
@@ -681,13 +681,14 @@
   for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
     {
       const char *regname;
+      int nregs;
 
       if (TREE_VALUE (tail) == error_mark_node)
 	return;
       regname = TREE_STRING_POINTER (TREE_VALUE (tail));
 
-      i = decode_reg_name (regname);
-      if (i >= 0 || i == -4)
+      i = decode_reg_name_and_count (regname, &nregs);
+      if (i == -4)
 	++nclobbers;
       else if (i == -2)
 	error ("unknown register name %qs in %<asm%>", regname);
@@ -695,14 +696,21 @@
       /* Mark clobbered registers.  */
       if (i >= 0)
         {
-	  /* Clobbering the PIC register is an error.  */
-	  if (i == (int) PIC_OFFSET_TABLE_REGNUM)
+	  int reg;
+
+	  for (reg = i; reg < i + nregs; reg++)
 	    {
-	      error ("PIC register %qs clobbered in %<asm%>", regname);
-	      return;
-	    }
+	      ++nclobbers;
+
+	      /* Clobbering the PIC register is an error.  */
+	      if (reg == (int) PIC_OFFSET_TABLE_REGNUM)
+		{
+		  error ("PIC register clobbered by %qs in %<asm%>", regname);
+		  return;
+		}
 
-	  SET_HARD_REG_BIT (clobbered_regs, i);
+	      SET_HARD_REG_BIT (clobbered_regs, reg);
+	    }
 	}
     }
 
@@ -1012,7 +1020,8 @@
       for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
 	{
 	  const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
-	  int j = decode_reg_name (regname);
+	  int reg, nregs;
+	  int j = decode_reg_name_and_count (regname, &nregs);
 	  rtx clobbered_reg;
 
 	  if (j < 0)
@@ -1034,30 +1043,39 @@
 	      continue;
 	    }
 
-	  /* Use QImode since that's guaranteed to clobber just one reg.  */
-	  clobbered_reg = gen_rtx_REG (QImode, j);
+	  for (reg = j; reg < j + nregs; reg++)
+	    {
+	      /* Use QImode since that's guaranteed to clobber just
+	       * one reg.  */
+	      clobbered_reg = gen_rtx_REG (QImode, reg);
+
+	      /* Do sanity check for overlap between clobbers and
+		 respectively input and outputs that hasn't been
+		 handled.  Such overlap should have been detected and
+		 reported above.  */
+	      if (!clobber_conflict_found)
+		{
+		  int opno;
+
+		  /* We test the old body (obody) contents to avoid
+		     tripping over the under-construction body.  */
+		  for (opno = 0; opno < noutputs; opno++)
+		    if (reg_overlap_mentioned_p (clobbered_reg,
+						 output_rtx[opno]))
+		      internal_error
+			("asm clobber conflict with output operand");
+
+		  for (opno = 0; opno < ninputs - ninout; opno++)
+		    if (reg_overlap_mentioned_p (clobbered_reg,
+						 ASM_OPERANDS_INPUT (obody,
+								     opno)))
+		      internal_error
+			("asm clobber conflict with input operand");
+		}
 
-	  /* Do sanity check for overlap between clobbers and respectively
-	     input and outputs that hasn't been handled.  Such overlap
-	     should have been detected and reported above.  */
-	  if (!clobber_conflict_found)
-	    {
-	      int opno;
-
-	      /* We test the old body (obody) contents to avoid tripping
-		 over the under-construction body.  */
-	      for (opno = 0; opno < noutputs; opno++)
-		if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
-		  internal_error ("asm clobber conflict with output operand");
-
-	      for (opno = 0; opno < ninputs - ninout; opno++)
-		if (reg_overlap_mentioned_p (clobbered_reg,
-					     ASM_OPERANDS_INPUT (obody, opno)))
-		  internal_error ("asm clobber conflict with input operand");
+	      XVECEXP (body, 0, i++)
+		= gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
 	    }
-
-	  XVECEXP (body, 0, i++)
-	    = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
 	}
 
       emit_insn (body);
diff -Naur a/src/gcc/target-def.h b/src/gcc/target-def.h
--- a/src/gcc/target-def.h	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/target-def.h	2010-03-30 10:39:47.000000000 +0300
@@ -240,6 +240,10 @@
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL NULL
 #endif
 
+#ifndef TARGET_ASM_FINAL_POSTSCAN_INSN
+#define TARGET_ASM_FINAL_POSTSCAN_INSN NULL
+#endif
+
 #ifndef TARGET_ASM_RECORD_GCC_SWITCHES
 #define TARGET_ASM_RECORD_GCC_SWITCHES NULL
 #endif
@@ -295,7 +299,8 @@
 			TARGET_ASM_RECORD_GCC_SWITCHES,		\
 			TARGET_ASM_RECORD_GCC_SWITCHES_SECTION,	\
 			TARGET_ASM_OUTPUT_ANCHOR,		\
-			TARGET_ASM_OUTPUT_DWARF_DTPREL}
+			TARGET_ASM_OUTPUT_DWARF_DTPREL,		\
+			TARGET_ASM_FINAL_POSTSCAN_INSN}
 
 /* Scheduler hooks.  All of these default to null pointers, which
    haifa-sched.c looks for and handles.  */
diff -Naur a/src/gcc/target.h b/src/gcc/target.h
--- a/src/gcc/target.h	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/target.h	2010-03-30 10:39:46.000000000 +0300
@@ -245,6 +245,8 @@
     /* Output a DTP-relative reference to a TLS symbol.  */
     void (*output_dwarf_dtprel) (FILE *file, int size, rtx x);
 
+    /* Some target machines need to postscan each insn after it is output.  */
+    void (*final_postscan_insn) (FILE *, rtx, rtx *, int);
   } asm_out;
 
   /* Functions relating to instruction scheduling.  */
diff -Naur a/src/gcc/targhooks.c b/src/gcc/targhooks.c
--- a/src/gcc/targhooks.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/targhooks.c	2010-03-30 10:39:46.000000000 +0300
@@ -65,7 +65,7 @@
 #include "reload.h"
 #include "optabs.h"
 #include "recog.h"
-
+#include "convert.h"
 
 void
 default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
@@ -444,8 +444,11 @@
 tree
 hook_cxx_ttype_ref_in_bit0 (tree exp)
 {
-  exp = convert (build_pointer_type (char_type_node), exp);
-  exp = pointer_int_sum (PLUS_EXPR, exp, integer_one_node);
+  tree pointer_type = build_pointer_type (char_type_node);
+  tree one = convert (sizetype, integer_one_node);
+  
+  exp = convert_to_pointer (pointer_type, exp);
+  exp = fold_build2 (POINTER_PLUS_EXPR, pointer_type, exp, one);
   
   return exp;
 }
diff -Naur a/src/gcc/toplev.c b/src/gcc/toplev.c
--- a/src/gcc/toplev.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/toplev.c	2010-04-02 10:28:17.000000000 +0300
@@ -2009,8 +2009,8 @@
 
   /* We may need to recompute regno_save_code[] and regno_restore_code[]
      after a mode change as well.  */
-  if (flag_caller_saves)
-    init_caller_save ();
+  caller_save_initialized_p = false;
+
   expand_dummy_function_end ();
 }
 
diff -Naur a/src/gcc/tree.c b/src/gcc/tree.c
--- a/src/gcc/tree.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/tree.c	2010-03-30 10:39:46.000000000 +0300
@@ -51,6 +51,7 @@
 #include "params.h"
 #include "pointer-set.h"
 #include "fixed-value.h"
+#include "intl.h"
 
 /* Tree code classes.  */
 
@@ -3568,9 +3569,9 @@
 expand_location (source_location loc)
 {
   expanded_location xloc;
-  if (loc == 0)
+  if (loc <= BUILTINS_LOCATION)
     {
-      xloc.file = NULL;
+      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
       xloc.line = 0;
       xloc.column = 0;
       xloc.sysp = 0;
@@ -7996,6 +7997,19 @@
 	return true;
       }
 
+    case STRING_CST:
+      {
+	int i;
+
+	/* We need to loop through all elements to handle cases like
+	   "\0" and "\0foobar".  */
+	for (i = 0; i < TREE_STRING_LENGTH (init); ++i)
+	  if (TREE_STRING_POINTER (init)[i] != '\0')
+	    return false;
+
+	return true;
+      }
+
     default:
       return false;
     }
diff -Naur a/src/gcc/tree-ssa-loop-promote.c b/src/gcc/tree-ssa-loop-promote.c
--- a/src/gcc/tree-ssa-loop-promote.c	2009-10-14 21:55:24.000000000 +0300
+++ b/src/gcc/tree-ssa-loop-promote.c	2010-03-30 10:39:47.000000000 +0300
@@ -130,6 +130,10 @@
 
 static struct pointer_set_t *promoted_stmts;
 
+/* Phi nodes that we have to fix up after we've promoted everything else.  */
+
+static struct pointer_set_t *phi_nodes_to_promote;
+
 
 /* Add CASTED to PI->CAST_TYPES if we haven't seen CASTED before.  */
 
@@ -1312,44 +1316,13 @@
       }
       break;
     case GIMPLE_PHI:
-      {
-	unsigned int i;
-	bool promoted_result = could_be_promoted (PHI_RESULT (stmt));
-
-	for (i = 0; i < gimple_phi_num_args (stmt); i++)
-	  {
-	    tree var = gimple_phi_arg_def (stmt, i);
-	    edge e = gimple_phi_arg_edge (stmt, i);
-	    gimple assign = NULL;
-
-	    if (TREE_CODE (var) == INTEGER_CST && promoted_result)
-	      {
-		tree cst = build_int_cst_wide (pi->promoted_type,
-					       TREE_INT_CST_LOW (var),
-					       TREE_INT_CST_HIGH (var));
-
-		assign = gimple_build_assign (pi->promoted_var, cst);
-		insert_along_edge (assign, e);
-	      }
-	    else if (TREE_CODE (var) == SSA_NAME
-		     && SSA_NAME_VAR (var) == pi->var_decl
-		     && !promoted_result)
-	      {
-		tree t = create_pli_var (TREE_TYPE (PHI_RESULT (stmt)),
-					 CONST_CAST (char *, "promotetmp"));
-		tree name;
-		assign = gimple_build_assign_with_ops (CONVERT_EXPR,
-						       t, pi->promoted_var,
-						       NULL_TREE);
-
-		name = make_ssa_name (t, assign);
-		gimple_assign_set_lhs (assign, name);
-
-		insert_along_edge (assign, e);
-		SET_PHI_ARG_DEF (stmt, i, name);
-	      }
-	  }
-      }
+      /* Save for later rebuilding.  Any rebuilding of a phi node will
+	 cause an incoming edge to be split, which means that the phi
+	 node may be reallocated, which means that keeping track of
+	 which statements have been rebuilt (by pointer equality) breaks
+	 down.  */
+      gsi = gsi_for_stmt (stmt);
+      pointer_set_insert (phi_nodes_to_promote, gsi_stmt_ptr (&gsi));
       break;
     default:
       gcc_unreachable ();
@@ -1406,6 +1379,90 @@
   return true;
 }
 
+static bool
+promote_phi_node (const void *phi_, void *data ATTRIBUTE_UNUSED)
+{
+  const gimple *cphi = (const gimple *) phi_;
+  gimple_stmt_iterator gsi = gsi_for_stmt (*cphi);
+  gimple *phi_p = gsi_stmt_ptr (&gsi);
+  gimple phi = *phi_p;
+  unsigned int i;
+  bool promoted_result = could_be_promoted (PHI_RESULT (phi));
+
+  /* There are two cases we have to be concerned about:
+
+     - If the result can be promoted, then any incoming INTEGER_CSTs
+       need to be assigned to the newly promoted variable, rather than
+       the promotable variable;
+
+     - If the result cannot be promoted, then we need to check if any of
+       the arguments are promotable.  For each argument that is, we need
+       to insert a truncating assignment to convert from the type of the
+       promoted variable to the type of the PHI_RESULT.
+
+     In both cases, we have to regrab the phi node after we've inserted
+     the new assignment along the appropriate edge, since
+     insert_along_edge might have reallocated the phi node.  */
+  for (i = 0; i < gimple_phi_num_args (phi); i++)
+    {
+      tree var = gimple_phi_arg_def (phi, i);
+      edge e = gimple_phi_arg_edge (phi, i);
+      gimple assign = NULL;
+
+      if (TREE_CODE (var) == INTEGER_CST && promoted_result)
+	{
+	  tree promoted, cst;
+	  void **p;
+	  
+	  p = pointer_map_contains (variable_map, PHI_RESULT (phi));
+	  gcc_assert (p);
+	  promoted = (tree) *p;
+	  cst = build_int_cst_wide (TREE_TYPE (promoted),
+				    TREE_INT_CST_LOW (var),
+				    TREE_INT_CST_HIGH (var));
+
+	  assign = gimple_build_assign (promoted, cst);
+	}
+      else if (!promoted_result
+	       && TREE_CODE (var) == SSA_NAME
+	       && could_be_promoted (var))
+	{
+	  tree promoted, t, name;
+	  void **p;
+
+	  p = pointer_map_contains (variable_map, var);
+	  gcc_assert (p);
+	  promoted = (tree) *p;
+
+	  if (dump_file)
+	    {
+	      fprintf (dump_file, "Inserting downcast of promoted variable ");
+	      print_generic_expr (dump_file, promoted, 0);
+	      fprintf (dump_file, "\n");
+	    }
+
+	  t = create_pli_var (TREE_TYPE (PHI_RESULT (phi)),
+			      CONST_CAST (char *, "promote_cast_tmp"));
+	  assign = gimple_build_assign_with_ops (CONVERT_EXPR,
+						 t, promoted,
+						 NULL_TREE);
+
+	  name = make_ssa_name (t, assign);
+	  gimple_assign_set_lhs (assign, name);
+	  SET_PHI_ARG_DEF (phi, i, name);
+	}
+
+      if (assign != NULL)
+	{
+	  insert_along_edge (assign, e);
+	  phi = *phi_p;
+	}
+    }
+
+  /* Continue traversal.  */
+  return true;
+}
+
 /* Free PI_ and its associated data.  */
 
 static bool
@@ -1488,6 +1545,11 @@
 static void
 pli_cleanup (void)
 {
+  if (phi_nodes_to_promote)
+    {
+      pointer_set_destroy (phi_nodes_to_promote);
+      phi_nodes_to_promote = NULL;
+    }
   if (promoted_stmts)
     {
       pointer_set_destroy (promoted_stmts);
@@ -1569,8 +1631,10 @@
       did_something = true;
       variable_map = pointer_map_create ();
       promoted_stmts = pointer_set_create ();
+      phi_nodes_to_promote = pointer_set_create ();
       pointer_set_traverse (promotion_info, create_promoted_variable, NULL);
       pointer_set_traverse (promotion_info, promote_variable, NULL);
+      pointer_set_traverse (phi_nodes_to_promote, promote_phi_node, NULL);
     }
 
  cleanup:
diff -Naur a/src/gcc/tree-ssa-remove-local-statics.c b/src/gcc/tree-ssa-remove-local-statics.c
--- a/src/gcc/tree-ssa-remove-local-statics.c	2009-10-14 21:55:24.000000000 +0300
+++ b/src/gcc/tree-ssa-remove-local-statics.c	2010-04-10 10:19:18.000000000 +0300
@@ -470,33 +470,47 @@
 {
   struct rls_stmt_info *info = (struct rls_stmt_info *) *slot;
   struct rls_decl_info dummy;
+  struct rls_decl_info *decl;
 
   /* We don't need to look at definitions.  Continue scanning.  */
   if (!info->use_p)
     return 1;
 
+  if (dump_file)
+    {
+      fprintf (dump_file, "defined bitmap for ");
+      print_gimple_stmt (dump_file, info->stmt, 0, 0);
+      fprintf (dump_file, " : ");
+      dump_sbitmap (dump_file, info->defined);
+    }
+
   dummy.orig_var = info->var;
-  slot = htab_find_slot (static_variables, &dummy, INSERT);
+  slot = htab_find_slot (static_variables, &dummy, NO_INSERT);
+
+  gcc_assert (slot);
+
+  decl = (struct rls_decl_info *) *slot;
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "with index %d for var ", decl->index);
+      print_generic_expr (dump_file, decl->orig_var, 0);
+      fprintf (dump_file, "\n\n");
+    }
 
-  /* Might not be there because we deleted it already.  */
-  if (*slot)
+  if (decl->optimizable_p && !TEST_BIT (info->defined, decl->index))
     {
-      struct rls_decl_info *decl = (struct rls_decl_info *) *slot;
+      if (dump_file)
+	{
+	  fprintf (dump_file, "not optimizing ");
+	  print_generic_expr (dump_file, decl->orig_var, 0);
+	  fprintf (dump_file, " due to uncovered use in ");
+	  print_gimple_stmt (dump_file, info->stmt, 0, 0);
+	  fprintf (dump_file, "\n");
+	}
 
-      if (!TEST_BIT (info->defined, decl->index))
-        {
-          if (dump_file)
-            {
-              fprintf (dump_file, "not optimizing ");
-              print_generic_expr (dump_file, decl->orig_var, 0);
-              fprintf (dump_file, "due to uncovered use in ");
-              print_gimple_stmt (dump_file, info->stmt, 0, 0);
-              fprintf (dump_file, "\n");
-            }
-
-          htab_clear_slot (static_variables, slot);
-          stats.n_optimizable--;
-        }
+      decl->optimizable_p = false;
+      stats.n_optimizable--;
     }
 
   /* Continue scan.  */
@@ -533,9 +547,9 @@
   tree vuse;
   int continue_scan = 1;
 
-  /* We should have removed unoptimizable variables during an earlier
-     traversal.  */
-  gcc_assert (info->optimizable_p);
+  /* Can't do anything to this variable.  */
+  if (!info->optimizable_p)
+    goto done;
 
   /* Check for virtual definitions first.  */
   vdef = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_VDEF);
@@ -702,10 +716,10 @@
 
 	  /* See if this statement uses or defines a static variable.  */
 	  dummy.stmt = stmt;
-	  slot = htab_find_slot (defuse_statements, &dummy, INSERT);
+	  slot = htab_find_slot (defuse_statements, &dummy, NO_INSERT);
 
 	  /* Check for uses.  */
-	  if (*slot != NULL)
+	  if (slot)
 	    {
 	      struct rls_stmt_info *info = (struct rls_stmt_info *) *slot;
 
@@ -728,9 +742,9 @@
 		     variable.  Look up the associated variable's information
 		     and mark it as defined in the block.  */
 		  dummy.orig_var = info->var;
-		  slot = htab_find_slot (static_variables, &dummy, INSERT);
+		  slot = htab_find_slot (static_variables, &dummy, NO_INSERT);
 
-		  gcc_assert (*slot);
+		  gcc_assert (slot);
 
 		  decl = (struct rls_decl_info *) *slot;
 
@@ -836,7 +850,10 @@
 
   rls_done ();
 
-  return 0;
+  if (stats.n_optimizable > 0)
+    return TODO_rebuild_alias | TODO_update_ssa;
+  else
+    return 0;
 }
 
 static bool
diff -Naur a/src/gcc/tsystem.h b/src/gcc/tsystem.h
--- a/src/gcc/tsystem.h	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/tsystem.h	2010-03-30 10:39:47.000000000 +0300
@@ -89,12 +89,14 @@
 /* All systems have this header.  */
 #include <sys/types.h>
 
-/* All systems have this header.  */
+#ifndef __MINGW32CE__
+/* All systems except Windows CE have this header.  */
 #include <errno.h>
 
 #ifndef errno
 extern int errno;
 #endif
+#endif
 
 /* GCC (fixproto) guarantees these system headers exist.  */
 #include <string.h>
diff -Naur a/src/gcc/varasm.c b/src/gcc/varasm.c
--- a/src/gcc/varasm.c	2009-10-12 21:21:10.000000000 +0300
+++ b/src/gcc/varasm.c	2010-04-10 10:19:16.000000000 +0300
@@ -1031,8 +1031,11 @@
    Prefixes such as % are optional.  */
 
 int
-decode_reg_name (const char *asmspec)
+decode_reg_name_and_count (const char *asmspec, int *pnregs)
 {
+  /* Presume just one register is clobbered.  */
+  *pnregs = 1;
+
   if (asmspec != 0)
     {
       int i;
@@ -1058,6 +1061,25 @@
 	    && ! strcmp (asmspec, strip_reg_name (reg_names[i])))
 	  return i;
 
+#ifdef OVERLAPPING_REGISTER_NAMES
+      {
+	static const struct
+	{
+	  const char *const name;
+	  const int number;
+	  const int nregs;
+	} table[] = OVERLAPPING_REGISTER_NAMES;
+
+	for (i = 0; i < (int) ARRAY_SIZE (table); i++)
+	  if (table[i].name[0]
+	      && ! strcmp (asmspec, table[i].name))
+	    {
+	      *pnregs = table[i].nregs;
+	      return table[i].number;
+	    }
+      }
+#endif /* OVERLAPPING_REGISTER_NAMES */
+
 #ifdef ADDITIONAL_REGISTER_NAMES
       {
 	static const struct { const char *const name; const int number; } table[]
@@ -1081,6 +1103,14 @@
 
   return -1;
 }
+
+int
+decode_reg_name (const char *name)
+{
+  int count;
+  return decode_reg_name_and_count (name, &count);
+}
+
 
 /* Return true if DECL's initializer is suitable for a BSS section.  */
 
diff -Naur a/src/gcc/vmsdbgout.c b/src/gcc/vmsdbgout.c
--- a/src/gcc/vmsdbgout.c	2009-10-12 21:21:09.000000000 +0300
+++ b/src/gcc/vmsdbgout.c	2010-03-30 10:39:47.000000000 +0300
@@ -166,6 +166,7 @@
 
 static void vmsdbgout_init (const char *);
 static void vmsdbgout_finish (const char *);
+static void vmsdbgout_assembly_start (void);
 static void vmsdbgout_define (unsigned int, const char *);
 static void vmsdbgout_undef (unsigned int, const char *);
 static void vmsdbgout_start_source_file (unsigned int, const char *);
@@ -188,6 +189,7 @@
 const struct gcc_debug_hooks vmsdbg_debug_hooks
 = {vmsdbgout_init,
    vmsdbgout_finish,
+   vmsdbgout_assembly_start,
    vmsdbgout_define,
    vmsdbgout_undef,
    vmsdbgout_start_source_file,
@@ -1637,6 +1639,15 @@
 /* Not implemented in VMS Debug.  */
 
 static void
+vmsdbgout_assembly_start (void)
+{
+  if (write_symbols == VMS_AND_DWARF2_DEBUG)
+    (*dwarf2_debug_hooks.assembly_start) ();
+}
+
+/* Not implemented in VMS Debug.  */
+
+static void
 vmsdbgout_define (unsigned int lineno, const char *buffer)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
diff -Naur a/src/libcpp/include/line-map.h b/src/libcpp/include/line-map.h
--- a/src/libcpp/include/line-map.h	2009-10-12 21:26:01.000000000 +0300
+++ b/src/libcpp/include/line-map.h	2010-03-30 10:42:18.000000000 +0300
@@ -144,6 +144,11 @@
 extern const struct line_map *linemap_lookup
   (struct line_maps *, source_location);
 
+/* source_location values from 0 to RESERVED_LOCATION_COUNT-1 will
+   be reserved for libcpp user as special values, no token from libcpp
+   will contain any of those locations.  */
+#define RESERVED_LOCATION_COUNT	2
+
 /* Converts a map and a source_location to source line.  */
 #define SOURCE_LINE(MAP, LOC) \
   ((((LOC) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line)
diff -Naur a/src/libcpp/line-map.c b/src/libcpp/line-map.c
--- a/src/libcpp/line-map.c	2009-10-12 21:26:03.000000000 +0300
+++ b/src/libcpp/line-map.c	2010-03-30 10:42:20.000000000 +0300
@@ -38,8 +38,8 @@
   set->trace_includes = false;
   set->depth = 0;
   set->cache = 0;
-  set->highest_location = 0;
-  set->highest_line = 0;
+  set->highest_location = RESERVED_LOCATION_COUNT - 1;
+  set->highest_line = RESERVED_LOCATION_COUNT - 1;
   set->max_column_hint = 0;
 }
 
diff -Naur a/src/libgcc/config/sh/t-uclinux-fdpic b/src/libgcc/config/sh/t-uclinux-fdpic
--- a/src/libgcc/config/sh/t-uclinux-fdpic	1970-01-01 02:00:00.000000000 +0200
+++ b/src/libgcc/config/sh/t-uclinux-fdpic	2010-03-30 10:32:17.000000000 +0300
@@ -0,0 +1,40 @@
+# FIXME: -DNO_FPSCR_VALUES is probably appropriate (we have shared libs).
+# But it requires __fpscr_values be provided by libc.so.
+HOST_LIBGCC2_CFLAGS = -fpic
+
+# Do we need unwind-dw2-fde-glibc for EH?  It does not currently
+# build.
+#LIB2ADDEH = $(gcc_srcdir)/unwind-dw2.c $(gcc_srcdir)/unwind-dw2-fde-glibc.c \
+#  $(gcc_srcdir)/unwind-sjlj.c $(gcc_srcdir)/gthr-gnat.c \
+#  $(gcc_srcdir)/unwind-c.c
+
+# Override t-slibgcc-elf-ver to hide some lib1func routines which
+# should not be called via PLT.
+SHLIB_MAPFILES += $(gcc_srcdir)/config/sh/libgcc-excl.ver
+
+# Override SHLIB_LINK and SHLIB_INSTALL to use linker script
+# libgcc_s.so.
+SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+	-Wl,--soname=@shlib_base_name@.so.1 \
+	-Wl,--version-script=@shlib_map_file@ \
+	-o @multilib_dir@/@shlib_base_name@.so.1.tmp @multilib_flags@ \
+	@shlib_objs@ -lc && \
+	rm -f @multilib_dir@/@shlib_base_name@.so && \
+	if [ -f @multilib_dir@/@shlib_base_name@.so.1 ]; then \
+	  mv -f @multilib_dir@/@shlib_base_name@.so.1 \
+		@multilib_dir@/@shlib_base_name@.so.1.backup; \
+	else true; fi && \
+	mv @multilib_dir@/@shlib_base_name@.so.1.tmp \
+	   @multilib_dir@/@shlib_base_name@.so.1 && \
+	(echo "/* GNU ld script"; \
+	 echo "   Use the shared library, but some functions are only in"; \
+	 echo "   the static library.  */"; \
+	 echo "GROUP ( @shlib_base_name@.so.1 libgcc.a )" \
+	) > @multilib_dir@/@shlib_base_name@.so
+SHLIB_INSTALL = \
+	$(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \
+	$(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so.1 \
+	  $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so.1; \
+	rm -f $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
+	$(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so \
+	  $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so
diff -Naur a/src/libgcc/config.host b/src/libgcc/config.host
--- a/src/libgcc/config.host	2009-10-12 21:15:37.000000000 +0300
+++ b/src/libgcc/config.host	2010-04-03 10:36:23.000000000 +0300
@@ -210,7 +210,7 @@
 	;;
 arm*-*-ecos-elf)
 	;;
-arm*-*-eabi* | arm*-*-symbianelf* )
+arm*-*-eabi* | arm*-*-nucleuseabi* | arm*-*-symbianelf* )
 	tmake_file="${tmake_file} arm/t-divmod-ef"
 	;;
 arm*-*-rtems*)
@@ -219,6 +219,8 @@
 	;;
 arm*-wince-pe*)
 	;;
+arm*-*-mingw32ce* | arm*-*-cegcc*)
+	;;
 arm-*-pe*)
 	;;
 avr-*-rtems*)
@@ -471,6 +473,9 @@
 powerpc-*-eabialtivec*)
 	;;
 powerpc-*-eabi*)
+	if test x"${ppc_has_spe}" = xyes; then
+		tmake_file="${tmake_file} rs6000/t-spe-fprules"
+	fi
 	;;
 powerpc-*-rtems*)
 	;;
@@ -482,6 +487,9 @@
 	;;
 powerpc-*-linux*)
 	tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ldbl128 t-softfp"
+	if test x"${ppc_has_spe}" = xyes; then
+		tmake_file="${tmake_file} rs6000/t-spe-fprules"
+	fi
 	;;
 powerpc-*-gnu-gnualtivec*)
 	tmake_file="${tmake_file} rs6000/t-ldbl128"
@@ -518,12 +526,20 @@
 sh-*-elf* | sh[12346l]*-*-elf* | \
 sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
   sh-*-linux* | sh[2346lbe]*-*-linux* | \
+  sh-*-uclinux* | sh[12]-*-uclinux* | \
   sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
    sh64-*-netbsd* | sh64l*-*-netbsd*)
 	case ${host} in
 	sh*-*-linux*)
 		tmake_file="${tmake_file} sh/t-linux"
 		;;
+	sh*-*-uclinux*)
+		# Upstream submission question: do we even need the
+		# pre-FDPIC configuration?
+		if test x$enable_fdpic != xno; then
+			tmake_file="${tmake_file} sh/t-uclinux-fdpic"
+		fi
+		;;
 	esac
 	;;
 sh-*-rtems*)
diff -Naur a/src/libgcc/configure b/src/libgcc/configure
--- a/src/libgcc/configure	2009-10-12 21:15:37.000000000 +0300
+++ b/src/libgcc/configure	2010-04-03 10:36:23.000000000 +0300
@@ -3417,6 +3417,22 @@
     ;;
 esac
 
+
+# Check SPE for rs6000.
+case ${host} in
+powerpc*)
+  cat > conftest.c <<EOF
+#ifdef __SPE__
+ppc_has_spe=yes
+#else
+ppc_has_spe=no
+#endif
+EOF
+    eval `${CC-cc} -E conftest.c | grep ppc_has_spe=`
+    rm -f conftest.c
+    ;;
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
diff -Naur a/src/libgcc/configure.ac b/src/libgcc/configure.ac
--- a/src/libgcc/configure.ac	2009-10-12 21:15:37.000000000 +0300
+++ b/src/libgcc/configure.ac	2010-04-03 10:36:23.000000000 +0300
@@ -168,6 +168,21 @@
     ;;
 esac
 
+# Check SPE for rs6000.
+case ${host} in
+powerpc*)
+  cat > conftest.c <<EOF
+#ifdef __SPE__
+ppc_has_spe=yes
+#else
+ppc_has_spe=no
+#endif
+EOF
+    eval `${CC-cc} -E conftest.c | grep ppc_has_spe=`
+    rm -f conftest.c
+    ;;
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
diff -Naur a/src/libgfortran/config.h.in b/src/libgfortran/config.h.in
--- a/src/libgfortran/config.h.in	2009-10-12 21:22:26.000000000 +0300
+++ b/src/libgfortran/config.h.in	2010-03-30 10:40:36.000000000 +0300
@@ -300,6 +300,9 @@
 /* libm includes erfl */
 #undef HAVE_ERFL
 
+/* errno.h exists */
+#undef HAVE_ERRNO_H
+
 /* Define to 1 if you have the <execinfo.h> header file. */
 #undef HAVE_EXECINFO_H
 
diff -Naur a/src/libgfortran/configure b/src/libgfortran/configure
--- a/src/libgfortran/configure	2009-10-12 21:22:26.000000000 +0300
+++ b/src/libgfortran/configure	2010-03-30 10:40:36.000000000 +0300
@@ -15652,6 +15652,152 @@
 fi
 
 
+if test "${ac_cv_header_errno_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for errno.h" >&5
+echo $ECHO_N "checking for errno.h... $ECHO_C" >&6
+if test "${ac_cv_header_errno_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5
+echo "${ECHO_T}$ac_cv_header_errno_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking errno.h usability" >&5
+echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <errno.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking errno.h presence" >&5
+echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <errno.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: errno.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: errno.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: errno.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: errno.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------------------ ##
+## Report this to the GNU Fortran Runtime Library lists.  ##
+## ------------------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for errno.h" >&5
+echo $ECHO_N "checking for errno.h... $ECHO_C" >&6
+if test "${ac_cv_header_errno_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_errno_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5
+echo "${ECHO_T}$ac_cv_header_errno_h" >&6
+
+fi
+if test $ac_cv_header_errno_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ERRNO_H 1
+_ACEOF
+
+fi
+
+
 
 
 inttype_headers=`echo inttypes.h sys/inttypes.h  | sed -e 's/,/ /g'`
@@ -16361,7 +16507,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16425,7 +16572,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16466,7 +16614,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16523,7 +16672,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16564,7 +16714,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16629,7 +16780,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16697,7 +16849,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 long longval () { return (long) (sizeof (void *)); }
 unsigned long ulongval () { return (long) (sizeof (void *)); }
 #include <stdio.h>
@@ -16785,7 +16938,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16849,7 +17003,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16890,7 +17045,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16947,7 +17103,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -16988,7 +17145,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17053,7 +17211,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17121,7 +17280,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 long longval () { return (long) (sizeof (long)); }
 unsigned long ulongval () { return (long) (sizeof (long)); }
 #include <stdio.h>
@@ -17209,7 +17369,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17273,7 +17434,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17314,7 +17476,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17371,7 +17534,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17412,7 +17576,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17477,7 +17642,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17545,7 +17711,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 long longval () { return (long) (sizeof (int)); }
 unsigned long ulongval () { return (long) (sizeof (int)); }
 #include <stdio.h>
@@ -17629,7 +17796,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17693,7 +17861,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17734,7 +17903,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17791,7 +17961,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17832,7 +18003,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17897,7 +18069,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -17965,7 +18138,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 long longval () { return (long) (sizeof (short)); }
 unsigned long ulongval () { return (long) (sizeof (short)); }
 #include <stdio.h>
@@ -18049,7 +18223,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -18113,7 +18288,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -18154,7 +18330,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -18211,7 +18388,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -18252,7 +18430,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -18317,7 +18496,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 int
 main ()
 {
@@ -18385,7 +18565,8 @@
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
+/* no standard headers */
+
 long longval () { return (long) (sizeof (char)); }
 unsigned long ulongval () { return (long) (sizeof (char)); }
 #include <stdio.h>
diff -Naur a/src/libgfortran/configure.ac b/src/libgfortran/configure.ac
--- a/src/libgfortran/configure.ac	2009-10-12 21:22:26.000000000 +0300
+++ b/src/libgfortran/configure.ac	2010-03-30 10:40:36.000000000 +0300
@@ -193,6 +193,7 @@
 AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/wait.h floatingpoint.h ieeefp.h)
 AC_CHECK_HEADERS(fenv.h fptrap.h float.h execinfo.h pwd.h)
 AC_CHECK_HEADER([complex.h],[AC_DEFINE([HAVE_COMPLEX_H], [1], [complex.h exists])])
+AC_CHECK_HEADER([errno.h],[AC_DEFINE([HAVE_ERRNO_H], [1], [errno.h exists])])
 GCC_HEADER_STDINT(gstdint.h)
 
 AC_CHECK_MEMBERS([struct stat.st_blksize])
diff -Naur a/src/libgfortran/intrinsics/access.c b/src/libgfortran/intrinsics/access.c
--- a/src/libgfortran/intrinsics/access.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/access.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,6 @@
 
 #include "libgfortran.h"
 
-#include <errno.h>
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
@@ -85,6 +84,6 @@
   file[name_len] = '\0';
 
   /* And make the call to access().  */
-  return (access (file, m) == 0 ? 0 : errno);
+  return (access (file, m) == 0 ? 0 : get_oserrno ());
 }
 #endif
diff -Naur a/src/libgfortran/intrinsics/chdir.c b/src/libgfortran/intrinsics/chdir.c
--- a/src/libgfortran/intrinsics/chdir.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/chdir.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
diff -Naur a/src/libgfortran/intrinsics/chmod.c b/src/libgfortran/intrinsics/chmod.c
--- a/src/libgfortran/intrinsics/chmod.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/chmod.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
diff -Naur a/src/libgfortran/intrinsics/env.c b/src/libgfortran/intrinsics/env.c
--- a/src/libgfortran/intrinsics/env.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/env.c	2010-03-30 10:40:32.000000000 +0300
@@ -61,7 +61,11 @@
   memcpy (name_nt, name, name_len);
   name_nt[name_len] = '\0'; 
 
-  res = getenv(name_nt);
+#ifndef __MINGW32CE__
+  res = getenv (name_nt);
+#else
+  res = NULL;
+#endif
 
   /* If res is NULL, it means that the environment variable didn't 
      exist, so just return.  */
@@ -137,7 +141,11 @@
   memcpy (name_nt, name, name_len);
   name_nt[name_len] = '\0'; 
   
-  res = getenv(name_nt);
+#ifndef __MINGW32CE__
+  res = getenv (name_nt);
+#else
+  res = NULL;
+#endif
 
   if (res == NULL)
     stat = GFC_NAME_DOES_NOT_EXIST;
diff -Naur a/src/libgfortran/intrinsics/gerror.c b/src/libgfortran/intrinsics/gerror.c
--- a/src/libgfortran/intrinsics/gerror.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/gerror.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 
@@ -33,7 +35,6 @@
    message corresponding to the last system error (C errno).
    CHARACTER(len=*), INTENT(OUT) :: MESSAGE  */
 
-#ifdef HAVE_STRERROR
 void PREFIX(gerror) (char *, gfc_charlen_type);
 export_proto_np(PREFIX(gerror));
 
@@ -41,11 +42,11 @@
 PREFIX(gerror) (char * msg, gfc_charlen_type msg_len)
 {
   int p_len;
-  char *p;
+  const char *p;
 
   memset (msg, ' ', msg_len); /* Blank the string.  */
 
-  p = strerror (errno);
+  p = get_oserror ();
   if (p == NULL)
     return;
 
@@ -55,4 +56,3 @@
   else
     memcpy (msg, p, p_len);
 }
-#endif
diff -Naur a/src/libgfortran/intrinsics/getcwd.c b/src/libgfortran/intrinsics/getcwd.c
--- a/src/libgfortran/intrinsics/getcwd.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/getcwd.c	2010-03-30 10:40:32.000000000 +0300
@@ -26,7 +26,9 @@
 #include "libgfortran.h"
 
 #include <string.h>
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
diff -Naur a/src/libgfortran/intrinsics/getlog.c b/src/libgfortran/intrinsics/getlog.c
--- a/src/libgfortran/intrinsics/getlog.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/getlog.c	2010-03-30 10:40:32.000000000 +0300
@@ -36,9 +36,60 @@
 
 /* Windows32 version */
 #if defined __MINGW32__ && !defined  HAVE_GETLOGIN
-#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
-#include <lmcons.h>  /* for UNLEN */ 
+#include <lmcons.h>  /* for UNLEN */
+#include <malloc.h>
+
+#ifdef __MINGW32CE__
+
+/* GetUserNameExA is only available on CE >= 4.  Load it
+   dynamically.  */
+typedef enum
+{
+  NameUnknown = 0,
+  /* ... */
+  NameWindowsCeLocal = 0x80000001
+} EXTENDED_NAME_FORMAT;
+
+static BOOLEAN
+ce_GetUserNameA (LPSTR lpNameBuffer, PULONG nSize)
+{
+  static HMODULE dll = INVALID_HANDLE_VALUE;
+  static BOOLEAN (*pGetUserNameEx) (EXTENDED_NAME_FORMAT, LPTSTR, PULONG);
+
+  WCHAR *wbuf = alloca (*nSize * 2);
+
+  if (dll == INVALID_HANDLE_VALUE)
+    {
+      dll = GetModuleHandle (L"coredll.dll");
+      if (dll == NULL)
+	{
+	  /* paranoia */
+	  SetLastError (ERROR_NOT_SUPPORTED);
+	  return FALSE;
+	}
+
+      pGetUserNameEx = (void*) GetProcAddress (dll, L"GetUserNameExW");
+    }
+
+  if (pGetUserNameEx == NULL)
+    {
+      SetLastError (ERROR_NOT_SUPPORTED);
+      return FALSE;
+    }
+
+  *nSize *= 2;
+  if (!(*pGetUserNameEx) (NameWindowsCeLocal, wbuf, nSize))
+    return FALSE;
+
+  *nSize /= 2;
+  wcstombs (lpNameBuffer, wbuf, *nSize);
+  return TRUE;
+}
+
+#undef GetUserName
+#define GetUserName ce_GetUserNameA
+#endif
 
 static char *
 w32_getlogin (void)
diff -Naur a/src/libgfortran/intrinsics/getXid.c b/src/libgfortran/intrinsics/getXid.c
--- a/src/libgfortran/intrinsics/getXid.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/getXid.c	2010-03-30 10:40:32.000000000 +0300
@@ -30,7 +30,7 @@
 
 #ifdef __MINGW32__
 #define HAVE_GETPID 1
-#include <process.h>
+#include <windows.h>
 #endif
 
 #ifdef HAVE_GETGID
@@ -51,7 +51,11 @@
 GFC_INTEGER_4
 PREFIX(getpid) (void)
 {
+#ifdef __MINGW32CE__
+  return (GFC_INTEGER_4) GetCurrentProcessId ();
+#else
   return getpid ();
+#endif
 }
 #endif
 
diff -Naur a/src/libgfortran/intrinsics/hostnm.c b/src/libgfortran/intrinsics/hostnm.c
--- a/src/libgfortran/intrinsics/hostnm.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/hostnm.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
@@ -37,8 +39,10 @@
 #if defined __MINGW32__ && !defined  HAVE_GETHOSTNAME
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
-#include <errno.h>
 
+#ifndef __MINGW32CE__
+
+/* Windows (non-CE) version.  */
 static int
 w32_gethostname (char *name, size_t len)
 {
@@ -67,6 +71,55 @@
   return 0;
 }
 
+#else
+
+/* There's no GetComputerName on Windows CE, but, we can read the
+   computer name from the registry, at "HKLM\\Ident\\Name".  The
+   Internet claims this is what's WinSock's gethostname does too.  */
+
+static int
+w32_gethostname (char *name, size_t len)
+{
+  DWORD res;
+  HKEY hKey;
+
+/* XXX: Is this limit valid on CE?  */
+#ifndef MAX_COMPUTERNAME_LENGTH
+#define MAX_COMPUTERNAME_LENGTH 15
+#endif
+
+  res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Ident", 0, KEY_READ, &hKey);
+  if (res == ERROR_SUCCESS)
+    {
+      WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 1];
+      DWORD type;
+      DWORD nbytes;
+
+      nbytes = sizeof (buffer);
+      res = RegQueryValueEx (hKey, L"Name", NULL, &type, (LPBYTE) buffer,
+			     &nbytes);
+      RegCloseKey (hKey);
+
+      if (res == ERROR_SUCCESS)
+	{
+	  if (((nbytes / 2) + 1) > len)
+	    {
+	      SetLastError (ERROR_INVALID_PARAMETER);
+	      /* Truncate as per POSIX spec.  We do not
+		 NUL-terminate. */
+	      nbytes = len * 2;
+	    }
+
+	  wcstombs (name, buffer, nbytes / 2);
+	  return 0;
+	}
+    }
+
+  return -1;
+}
+
+#endif
+
 #undef gethostname
 #define gethostname w32_gethostname
 #define  HAVE_GETHOSTNAME 1
@@ -101,7 +154,7 @@
   }
 
   if (status != NULL) 
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 iexport(hostnm_i4_sub);
 
@@ -127,7 +180,7 @@
   }
 
   if (status != NULL) 
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 iexport(hostnm_i8_sub);
 
diff -Naur a/src/libgfortran/intrinsics/ierrno.c b/src/libgfortran/intrinsics/ierrno.c
--- a/src/libgfortran/intrinsics/ierrno.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/ierrno.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,9 +25,6 @@
 
 #include "libgfortran.h"
 
-#include <errno.h>
-
-
 /* INTEGER FUNCTION IERRNO()  */
 
 extern GFC_INTEGER_4 ierrno_i4 (void);
@@ -36,7 +33,7 @@
 GFC_INTEGER_4
 ierrno_i4 (void)
 {
-  return (GFC_INTEGER_4) errno;
+  return get_oserrno ();
 }
 
 extern GFC_INTEGER_8 ierrno_i8 (void);
@@ -45,5 +42,5 @@
 GFC_INTEGER_8
 ierrno_i8 (void)
 {
-  return (GFC_INTEGER_8) errno;
+  return (GFC_INTEGER_8) get_oserrno ();
 }
diff -Naur a/src/libgfortran/intrinsics/kill.c b/src/libgfortran/intrinsics/kill.c
--- a/src/libgfortran/intrinsics/kill.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/kill.c	2010-03-30 10:40:32.000000000 +0300
@@ -24,7 +24,9 @@
 <http://www.gnu.org/licenses/>.  */
 
 #include "libgfortran.h"
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
diff -Naur a/src/libgfortran/intrinsics/link.c b/src/libgfortran/intrinsics/link.c
--- a/src/libgfortran/intrinsics/link.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/link.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
diff -Naur a/src/libgfortran/intrinsics/perror.c b/src/libgfortran/intrinsics/perror.c
--- a/src/libgfortran/intrinsics/perror.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/perror.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,9 +25,18 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
+#ifdef __MINGW32CE__
+extern void pwinerror (const char *s);
+internal_proto(pwinerror);
+#define perror pwinerror
+#define HAVE_PERROR 1
+#endif
+
 /* SUBROUTINE PERROR(STRING)
    CHARACTER(len=*), INTENT(IN) :: STRING   */
 
diff -Naur a/src/libgfortran/intrinsics/rename.c b/src/libgfortran/intrinsics/rename.c
--- a/src/libgfortran/intrinsics/rename.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/rename.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 /* SUBROUTINE RENAME(PATH1, PATH2, STATUS)
@@ -61,7 +63,7 @@
   val = rename (str1, str2);
 
   if (status != NULL) 
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 iexport(rename_i4_sub);
 
@@ -94,7 +96,7 @@
   val = rename (str1, str2);
 
   if (status != NULL) 
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 iexport(rename_i8_sub);
 
diff -Naur a/src/libgfortran/intrinsics/signal.c b/src/libgfortran/intrinsics/signal.c
--- a/src/libgfortran/intrinsics/signal.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/signal.c	2010-03-30 10:40:32.000000000 +0300
@@ -37,14 +37,32 @@
 #include <inttypes.h>
 #endif
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
+
+#ifdef __MINGW32CE__
+# include <windows.h>
+#endif
+
+static void
+not_supported (void)
+{
+#if defined __MINGW32CE__
+  SetLastError (ERROR_NOT_SUPPORTED);
+#else
+  errno = ENOSYS;
+#endif
+}
 
 /* SIGNAL subroutine with PROCEDURE as handler  */
 extern void signal_sub (int *, void (*)(int), int *);
 iexport_proto(signal_sub);
 
 void
-signal_sub (int *number, void (*handler)(int), int *status)
+signal_sub (int *number __attribute__ ((unused)),
+	    void (*handler)(int) __attribute__ ((unused)),
+	    int *status)
 {
 #ifdef HAVE_SIGNAL
   intptr_t ret;
@@ -57,7 +75,7 @@
   else
     signal (*number, handler);
 #else
-  errno = ENOSYS;
+  not_supported ();
   if (status != NULL)
     *status = -1;
 #endif
@@ -70,7 +88,9 @@
 iexport_proto(signal_sub_int);
 
 void
-signal_sub_int (int *number, int *handler, int *status)
+signal_sub_int (int *number __attribute__ ((unused)),
+		int *handler __attribute__ ((unused)),
+		int *status)
 {
 #ifdef HAVE_SIGNAL
   intptr_t ptr = *handler, ret;
@@ -83,7 +103,7 @@
   else
     signal (*number, (void (*)(int)) ptr);
 #else
-  errno = ENOSYS;
+  not_supported ();
   if (status != NULL)
     *status = -1;
 #endif
@@ -143,7 +163,7 @@
       alarm (*seconds);
     }
 #else
-  errno = ENOSYS;
+  not_supported ();
   if (status != NULL)
     *status = -1;
 #endif
@@ -173,7 +193,7 @@
       alarm (*seconds);
     }
 #else
-  errno = ENOSYS;
+  not_supported ();
   if (status != NULL)
     *status = -1;
 #endif
@@ -204,7 +224,7 @@
       alarm (*seconds);
     }
 #else
-  errno = ENOSYS;
+  not_supported ();
   if (status != NULL)
     *status = -1;
 #endif
@@ -234,7 +254,7 @@
       alarm (*seconds);
     }
 #else
-  errno = ENOSYS;
+  not_supported ();
   if (status != NULL)
     *status = -1;
 #endif
diff -Naur a/src/libgfortran/intrinsics/sleep.c b/src/libgfortran/intrinsics/sleep.c
--- a/src/libgfortran/intrinsics/sleep.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/sleep.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,8 +25,6 @@
 
 #include "libgfortran.h"
 
-#include <errno.h>
-
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
diff -Naur a/src/libgfortran/intrinsics/stat.c b/src/libgfortran/intrinsics/stat.c
--- a/src/libgfortran/intrinsics/stat.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/stat.c	2010-03-30 10:40:32.000000000 +0300
@@ -26,7 +26,6 @@
 #include "libgfortran.h"
 
 #include <string.h>
-#include <errno.h>
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -141,7 +140,7 @@
     }
 
   if (status != NULL)
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 
 
@@ -260,7 +259,7 @@
     }
 
   if (status != NULL)
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 
 
@@ -439,7 +438,7 @@
     }
 
   if (status != NULL)
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 iexport(fstat_i4_sub);
 
@@ -520,7 +519,7 @@
     }
 
   if (status != NULL)
-    *status = (val == 0) ? 0 : errno;
+    *status = (val == 0) ? 0 : get_oserrno ();
 }
 iexport(fstat_i8_sub);
 
diff -Naur a/src/libgfortran/intrinsics/symlnk.c b/src/libgfortran/intrinsics/symlnk.c
--- a/src/libgfortran/intrinsics/symlnk.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/symlnk.c	2010-03-30 10:40:32.000000000 +0300
@@ -25,7 +25,9 @@
 
 #include "libgfortran.h"
 
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 
 #ifdef HAVE_UNISTD_H
diff -Naur a/src/libgfortran/intrinsics/system.c b/src/libgfortran/intrinsics/system.c
--- a/src/libgfortran/intrinsics/system.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/system.c	2010-03-30 10:40:32.000000000 +0300
@@ -30,6 +30,10 @@
 #include <stdlib.h>
 #endif
 
+#ifdef __MINGW32CE__
+#include <windows.h>
+#endif
+
 extern void system_sub (const char *fcmd, GFC_INTEGER_4 * status,
 			gfc_charlen_type cmd_len);
 iexport_proto(system_sub);
@@ -45,8 +49,14 @@
 
   memcpy (cmd, fcmd, cmd_len);
   cmd[cmd_len] = '\0';
-
+#ifndef __MINGW32CE__
   stat = system (cmd);
+#else
+  /* XXX: We could use ShellExecuteEx or
+     CreateProcess/WaitForSingleObject to implement this.  */
+  stat = -1;
+  SetLastError (ERROR_NOT_SUPPORTED);
+#endif
   if (status)
     *status = stat;
 }
diff -Naur a/src/libgfortran/intrinsics/umask.c b/src/libgfortran/intrinsics/umask.c
--- a/src/libgfortran/intrinsics/umask.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/umask.c	2010-03-30 10:40:32.000000000 +0300
@@ -38,6 +38,17 @@
 #include <unistd.h>
 #endif
 
+#ifdef __MINGW32CE__
+
+static mode_t
+ce_umask (mode_t m)
+{
+  /* XXX: Is there anything more sensible to do?  */
+  return 0 * m; /* avoid unused warning */
+}
+
+#define umask ce_umask
+#endif
 
 /* SUBROUTINE UMASK(MASK, OLD)
    INTEGER, INTENT(IN) :: MASK
diff -Naur a/src/libgfortran/intrinsics/unlink.c b/src/libgfortran/intrinsics/unlink.c
--- a/src/libgfortran/intrinsics/unlink.c	2009-10-12 21:22:18.000000000 +0300
+++ b/src/libgfortran/intrinsics/unlink.c	2010-03-30 10:40:32.000000000 +0300
@@ -26,7 +26,6 @@
 #include "libgfortran.h"
 
 #include <string.h>
-#include <errno.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -58,7 +57,7 @@
   stat = unlink (str);
 
   if (status != NULL)
-    *status = (stat == 0) ? stat : errno;
+    *status = (stat == 0) ? stat : get_oserrno ();
 }
 iexport(unlink_i4_sub);
 
diff -Naur a/src/libgfortran/io/open.c b/src/libgfortran/io/open.c
--- a/src/libgfortran/io/open.c	2009-10-12 21:22:25.000000000 +0300
+++ b/src/libgfortran/io/open.c	2010-03-30 10:40:35.000000000 +0300
@@ -27,8 +27,13 @@
 #include "io.h"
 #include <unistd.h>
 #include <string.h>
+#ifdef HAVE_ERRNO_H
 #include <errno.h>
+#endif
 
+#ifdef __MINGW32CE__
+#include <windows.h>
+#endif
 
 static const st_option access_opt[] = {
   {"sequential", ACCESS_SEQUENTIAL},
@@ -505,9 +510,28 @@
       msg = (char *) gfc_alloca (opp->file_len + 51);
       unpack_filename (path, opp->file, opp->file_len);
 
+#ifdef _WIN32_WCE
+      switch (GetLastError ())
+	{
+	case ERROR_FILE_NOT_FOUND:
+	  sprintf (msg, "File '%s' does not exist", path);
+	  break;
+
+	case ERROR_FILE_EXISTS:
+	  sprintf (msg, "File '%s' already exists", path);
+	  break;
+
+	case ERROR_ACCESS_DENIED:
+	  sprintf (msg, "Permission denied trying to open file '%s'", path);
+	  break;
+
+	default:
+	  msg = NULL;
+	}
+#else
       switch (errno)
 	{
-	case ENOENT: 
+	case ENOENT:
 	  sprintf (msg, "File '%s' does not exist", path);
 	  break;
 
@@ -526,6 +550,7 @@
 	default:
 	  msg = NULL;
 	}
+#endif
 
       generate_error (&opp->common, LIBERROR_OS, msg);
       goto cleanup;
diff -Naur a/src/libgfortran/io/read.c b/src/libgfortran/io/read.c
--- a/src/libgfortran/io/read.c	2009-10-12 21:22:25.000000000 +0300
+++ b/src/libgfortran/io/read.c	2010-03-30 10:40:35.000000000 +0300
@@ -25,11 +25,17 @@
 
 #include "io.h"
 #include <string.h>
-#include <errno.h>
+#ifdef HAVE_ERRNO_H
+# include <errno.h>
+#endif
 #include <ctype.h>
 #include <stdlib.h>
 #include <assert.h>
 
+#ifdef __MINGW32CE__
+# include <windows.h>
+#endif
+
 typedef unsigned char uchar;
 
 /* read.c -- Deal with formatted reads */
@@ -134,7 +140,11 @@
 int
 convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
 {
+#ifdef __MINGW32CE__
+  SetLastError (0);
+#else
   errno = 0;
+#endif
 
   switch (length)
     {
@@ -167,7 +177,13 @@
       internal_error (&dtp->common, "Unsupported real kind during IO");
     }
 
+#ifndef __MINGW32CE__
   if (errno == EINVAL)
+#else
+    /* TESTME: It is not clear if CE ever sets a last error at
+       all.  */
+  if (GetLastError () == ERROR_INVALID_PARAMETER)
+#endif
     {
       generate_error (&dtp->common, LIBERROR_READ_VALUE,
 		      "Error during floating point read");
diff -Naur a/src/libgfortran/io/transfer.c b/src/libgfortran/io/transfer.c
--- a/src/libgfortran/io/transfer.c	2009-10-12 21:22:25.000000000 +0300
+++ b/src/libgfortran/io/transfer.c	2010-03-30 10:40:35.000000000 +0300
@@ -32,8 +32,6 @@
 #include <string.h>
 #include <assert.h>
 #include <stdlib.h>
-#include <errno.h>
-
 
 /* Calling conventions:  Data transfer statements are unlike other
    library calls in that they extend over several calls.
@@ -2707,11 +2705,11 @@
 	{
 	  do
 	    {
-              errno = 0;
+	      clear_oserrno ();
               cc = fbuf_getc (dtp->u.p.current_unit);
 	      if (cc == EOF) 
 		{
-                  if (errno != 0)
+		  if (get_oserrno () != 0)
                     generate_error (&dtp->common, LIBERROR_OS, NULL);
                   else
                     hit_eof (dtp);
diff -Naur a/src/libgfortran/io/unix.c b/src/libgfortran/io/unix.c
--- a/src/libgfortran/io/unix.c	2009-10-12 21:22:25.000000000 +0300
+++ b/src/libgfortran/io/unix.c	2010-03-30 10:40:35.000000000 +0300
@@ -36,8 +36,10 @@
 #include <assert.h>
 
 #include <string.h>
-#include <errno.h>
 
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
 
 /* For mingw, we don't identify files by their inode number, but by a
    64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
@@ -68,13 +70,23 @@
 {
   HANDLE hFile;
   uint64_t res;
+#ifdef __MINGW32CE__
+  WCHAR wpath[MAX_PATH];
+#endif
 
   if (!path || !*path || access (path, F_OK))
     return (uint64_t) -1;
 
-  hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
-		      FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
-		      NULL);
+#ifdef __MINGW32CE__
+  MultiByteToWideChar (CP_ACP, 0, path, -1, wpath, MAX_PATH);
+  hFile = CreateFileW (wpath,
+#else
+  hFile = CreateFileA (path,
+#endif
+		       0, 0, NULL, OPEN_EXISTING,
+		       FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
+		       NULL);
+
   res = id_from_handle (hFile);
   CloseHandle (hFile);
   return res;
@@ -84,7 +96,11 @@
 static uint64_t
 id_from_fd (const int fd)
 {
+#ifdef __MINGW32CE__
+  return id_from_handle ((HANDLE) fd);
+#else
   return id_from_handle ((HANDLE) _get_osfhandle (fd));
+#endif
 }
 
 #endif
@@ -190,6 +206,14 @@
   return fd;
 }
 
+/* On Windows CE, file descriptors are actually pointers.  For the
+   most part, we pretend they're integers (sizeof(void*) == sizeof
+   (int), and INVALID_FILE_HANDLE is (void*)-1.  These hide a bit the
+   fact, avoiding integer/pointer comparison warnings.  */
+
+#define GFC_STDOUT_FILENO ((int) STDOUT_FILENO)
+#define GFC_STDERR_FILENO ((int) STDERR_FILENO)
+#define GFC_STDIN_FILENO ((int) STDIN_FILENO)
 
 /* If the stream corresponds to a preconnected unit, we flush the
    corresponding C stream.  This is bugware for mixed C-Fortran codes
@@ -200,22 +224,127 @@
   int fd;
 
   fd = ((unix_stream *) s)->fd;
-  if (fd == STDIN_FILENO)
+  if (fd == GFC_STDIN_FILENO)
     fflush (stdin);
-  else if (fd == STDOUT_FILENO)
+  else if (fd == GFC_STDOUT_FILENO)
     fflush (stdout);
-  else if (fd == STDERR_FILENO)
+  else if (fd == GFC_STDERR_FILENO)
     fflush (stderr);
 }
 
+#ifdef _WIN32
+
+#include <stdio.h>
+#include <windows.h>
+
+#ifndef COUNTOF
+#define COUNTOF(ARRAY) (sizeof (ARRAY) / sizeof ((ARRAY)[0]))
+#endif
+
+/* Map the Windows error number in ERROR to a locale-dependent error
+   message string and return a pointer to it.  Typically, the values
+   for ERROR come from GetLastError.
+
+   The string pointed to shall not be modified by the application, but
+   may be overwritten by a subsequent call to strwinerror
+
+   The strwinerror function does not change the current setting of
+   GetLastError.  */
+
+static char *
+strwinerror (DWORD error)
+{
+  static char buf[1024];
+  TCHAR *msgbuf;
+  DWORD lasterr = GetLastError ();
+  DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
+			       | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+			       NULL,
+			       error,
+			       0, /* Default language */
+			       (LPVOID)&msgbuf,
+			       0,
+			       NULL);
+  if (chars != 0)
+    {
+      /* If there is an \r\n appended, zap it.  */
+      if (chars >= 2
+	  && msgbuf[chars - 2] == '\r'
+	  && msgbuf[chars - 1] == '\n')
+	{
+	  chars -= 2;
+	  msgbuf[chars] = 0;
+	}
+
+      if (chars > ((COUNTOF (buf)) - 1))
+	{
+	  chars = COUNTOF (buf) - 1;
+	  msgbuf [chars] = 0;
+	}
+
+#ifdef UNICODE
+      wcstombs (buf, msgbuf, chars + 1);
+#else
+      strncpy (buf, msgbuf, chars + 1);
+#endif
+      LocalFree (msgbuf);
+    }
+  else
+    sprintf (buf, "unknown win32 error (%ld)", error);
+
+  SetLastError (lasterr);
+  return buf;
+}
+
+extern void pwinerror (const char *s);
+internal_proto(pwinerror);
+
+void
+pwinerror (const char *s)
+{
+  if (s && *s)
+    fprintf (stderr, "%s: %s\n", s, strwinerror (GetLastError ()));
+  else
+    fprintf (stderr, "%s\n", strwinerror (GetLastError ()));
+}
+
+#endif
 
 /* get_oserror()-- Get the most recent operating system error.  For
- * unix, this is errno. */
+ * unix, this is errno; for Windows CE, this is GetLastError.  */
 
 const char *
 get_oserror (void)
 {
+#ifdef __MINGW32CE__
+  return strwinerror (GetLastError ());
+#else
   return strerror (errno);
+#endif
+}
+
+/* get_oserrno()-- Get the most recent operating system error.  For
+ * unix and Windows, this is errno; for Windows CE, this is
+ * GetLastError.  */
+
+GFC_INTEGER_4
+get_oserrno (void)
+{
+#ifdef __MINGW32CE__
+  return (GFC_INTEGER_4) GetLastError ();
+#else
+  return errno;
+#endif
+}
+
+void
+clear_oserrno (void)
+{
+#ifdef __MINGW32CE__
+  SetLastError (0);
+#else
+  errno = 0;
+#endif
 }
 
 
@@ -261,10 +390,11 @@
       trans = write (s->fd, buf_st, bytes_left);
       if (trans < 0)
 	{
+#ifdef EINTR
 	  if (errno == EINTR)
 	    continue;
-	  else
-	    return trans;
+#endif
+	  return trans;
 	}
       buf_st += trans;
       bytes_left -= trans;
@@ -303,9 +433,9 @@
 {
   int retval;
   
-  if (s->fd != STDOUT_FILENO
-      && s->fd != STDERR_FILENO
-      && s->fd != STDIN_FILENO)
+  if (s->fd != GFC_STDOUT_FILENO
+      && s->fd != GFC_STDERR_FILENO
+      && s->fd != GFC_STDIN_FILENO)
     retval = close (s->fd);
   else
     retval = 0;
@@ -487,7 +617,11 @@
     }
   if (offset < 0)
     {
+#ifdef __MINGW32CE__
+      SetLastError (ERROR_INVALID_PARAMETER);
+#else
       errno = EINVAL;
+#endif
       return -1;
     }
   s->logical_offset = offset;
@@ -652,7 +786,11 @@
      negative offset, so don't check for that.  */
   if (offset > s->file_length)
     {
+#ifdef __MINGW32CE__
+      SetLastError (ERROR_INVALID_PARAMETER);
+#else
       errno = EINVAL;
+#endif
       return -1;
     }
 
@@ -747,6 +885,9 @@
 static stream *
 fd_to_stream (int fd, int prot)
 {
+#ifdef __MINGW32CE__
+  BY_HANDLE_FILE_INFORMATION fi;
+#endif
   struct stat statbuf;
   unix_stream *s;
 
@@ -761,7 +902,28 @@
 
   /* Get the current length of the file. */
 
+#ifdef __MINGW32CE__
+  /* mingw32ce's implementation of fstat is currently incorrect.  */
+  statbuf.st_mode = 0;
+  statbuf.st_size = -1;
+  if (fd == GFC_STDIN_FILENO || fd == GFC_STDOUT_FILENO
+      || fd == GFC_STDERR_FILENO)
+    statbuf.st_mode = S_IFCHR;
+  else
+      if (GetFileInformationByHandle ((HANDLE) fd, &fi))
+	{
+	  if (fi.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
+	    statbuf.st_mode = S_IFCHR;
+	  else
+	    if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+	      statbuf.st_mode = S_IFDIR;
+	    else
+	      statbuf.st_mode = S_IFREG;
+	  statbuf.st_size = fi.nFileSizeLow;
+	}
+#else
   fstat (fd, &statbuf);
+#endif
 
   if (lseek (fd, 0, SEEK_CUR) == (off_t) -1)
     s->file_length = -1;
@@ -770,14 +932,25 @@
 
   s->special_file = !S_ISREG (statbuf.st_mode);
 
+#ifdef __MINGW32CE__
+  if (options.all_unbuffered
+      ||(options.unbuffered_preconnected &&
+         (s->fd == GFC_STDIN_FILENO
+          || s->fd == GFC_STDOUT_FILENO
+          || s->fd == GFC_STDERR_FILENO)))
+    raw_init (s);
+  else
+    buf_init (s);
+#else
   if (isatty (s->fd) || options.all_unbuffered
       ||(options.unbuffered_preconnected && 
-         (s->fd == STDIN_FILENO 
-          || s->fd == STDOUT_FILENO 
-          || s->fd == STDERR_FILENO)))
+         (s->fd == GFC_STDIN_FILENO
+          || s->fd == GFC_STDOUT_FILENO
+          || s->fd == GFC_STDERR_FILENO)))
     raw_init (s);
   else
     buf_init (s);
+#endif
 
   return (stream *) s;
 }
@@ -818,6 +991,55 @@
   return 0;
 }
 
+#ifdef __MINGW32CE__
+
+static char *
+ce_mktemp (char *temp)
+{
+  char *string = temp;
+  unsigned number;
+  int letter = 'a';
+  int xcount = 0;
+  DWORD old_lasterror;
+
+  number = GetCurrentProcessId ();
+
+  while (*string != '\0')
+    string++;
+
+  while (*--string == 'X')
+    {
+      xcount++;
+      *string = (char) ((number % 10) + '0');
+      number /= 10;
+    }
+
+  /* FIXME: process ids on CE are really handles/pointers, so 6 digits
+     isn't enough.  Write hex over the XXXXXX instead?  */
+  if (*++string == '\0' || xcount != 6)
+    return NULL;
+
+  old_lasterror = GetLastError ();
+  SetLastError (0);
+
+  while (access (temp, F_OK) == 0)
+    {
+      if (letter == 'z' + 1)
+	{
+	  temp = NULL;
+	  break;
+	}
+
+      SetLastError (0);
+      *string = (char) letter++;
+    }
+
+  SetLastError (old_lasterror);
+  return temp;
+}
+
+#define mktemp ce_mktemp
+#endif
 
 /* tempfile()-- Generate a temporary filename for a scratch file and
  * open it.  mkstemp() opens the file for reading and writing, but the
@@ -829,15 +1051,17 @@
 static int
 tempfile (st_parameter_open *opp)
 {
-  const char *tempdir;
+  const char *tempdir = NULL;
   char *template;
   int fd;
 
+#ifndef __MINGW32CE__
   tempdir = getenv ("GFORTRAN_TMPDIR");
   if (tempdir == NULL)
     tempdir = getenv ("TMP");
   if (tempdir == NULL)
     tempdir = getenv ("TEMP");
+#endif
   if (tempdir == NULL)
     tempdir = DEFAULT_TEMPDIR;
 
@@ -851,6 +1075,14 @@
 
 #else /* HAVE_MKSTEMP */
 
+#ifndef __MINGW32CE__
+# define error_file_exists (errno == EEXIST)
+#else
+# define error_file_exists			\
+  (GetLastError () == ERROR_FILE_EXISTS		\
+   || GetLastError () == ERROR_ALREADY_EXISTS)
+#endif
+
   if (mktemp (template))
     do
 #if defined(HAVE_CRLF) && defined(O_BINARY)
@@ -859,13 +1091,14 @@
 #else
       fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
 #endif
-    while (!(fd == -1 && errno == EEXIST) && mktemp (template));
+    while (!(fd == -1 && error_file_exists) && mktemp (template));
   else
     fd = -1;
 
 #endif /* HAVE_MKSTEMP */
 
-  if (fd < 0)
+  /* Values < -1 are forbidden by POSIX but indicate success on Windows CE.  */
+  if (fd == -1)
     free_mem (template);
   else
     {
@@ -893,7 +1126,12 @@
 
   if (unpack_filename (path, opp->file, opp->file_len))
     {
-      errno = ENOENT;		/* Fake an OS error */
+      /* Fake an OS error */
+#ifndef __MINGW32CE__
+      errno = ENOENT;
+#else
+      SetLastError (ERROR_FILE_NOT_FOUND);
+#endif
       return -1;
     }
 
@@ -952,30 +1190,58 @@
   if (flags->action != ACTION_UNSPECIFIED)
     return fd;
 
-  if (fd >= 0)
+  /* Values < -1 are forbidden by POSIX but indicate success on Windows CE.  */
+  if (fd != -1)
     {
       flags->action = ACTION_READWRITE;
       return fd;
     }
+#ifndef __MINGW32CE__
   if (errno != EACCES && errno != EROFS)
-     return fd;
+    return fd;
+#else
+  switch (GetLastError ())
+    {
+    case ERROR_WRITE_PROTECT:
+    case ERROR_ACCESS_DENIED:
+    case ERROR_LOCK_VIOLATION:
+    case ERROR_SHARING_VIOLATION:
+      break;
+    default:
+      return fd;
+    }
+#endif
 
   /* retry for read-only access */
   rwflag = O_RDONLY;
   fd = open (path, rwflag | crflag, mode);
-  if (fd >=0)
+  /* Values < -1 are forbidden by POSIX but indicate success on Windows CE.  */
+  if (fd != -1)
     {
       flags->action = ACTION_READ;
       return fd;		/* success */
     }
   
+#ifndef __MINGW32CE__
   if (errno != EACCES)
     return fd;			/* failure */
+#else
+  switch (GetLastError ())
+    {
+    case ERROR_ACCESS_DENIED:
+    case ERROR_LOCK_VIOLATION:
+    case ERROR_SHARING_VIOLATION:
+      break;
+    default:
+      return fd;	        /* failure */
+    }
+#endif
 
   /* retry for write-only access */
   rwflag = O_WRONLY;
   fd = open (path, rwflag | crflag, mode);
-  if (fd >=0)
+  /* Values < -1 are forbidden by POSIX but indicate success on Windows CE.  */
+  if (fd != -1)
     {
       flags->action = ACTION_WRITE;
       return fd;		/* success */
@@ -1001,7 +1267,9 @@
 
 #if HAVE_UNLINK_OPEN_FILE
       /* We can unlink scratch files now and it will go away when closed. */
-      if (fd >= 0)
+      /* Values < -1 are forbidden by POSIX but indicate success on Windows
+	 CE.  */
+      if (fd != -1)
 	unlink (opp->file);
 #endif
     }
@@ -1012,7 +1280,7 @@
       fd = regular_file (opp, flags);
     }
 
-  if (fd < 0)
+  /* Values < -1 are forbidden by POSIX but indicate success on Windows CE.  */  if (fd == -1)
     return NULL;
   fd = fix_fd (fd);
 
@@ -1044,9 +1312,17 @@
 stream *
 input_stream (void)
 {
-  return fd_to_stream (STDIN_FILENO, PROT_READ);
+  return fd_to_stream (GFC_STDIN_FILENO, PROT_READ);
 }
 
+#ifdef __MINGW32CE__
+/* libcoredll.a exports this, and MSDN claims it exists on CE, but,
+   the mingw32ce headers don't export it.  We should fix the headers.
+   Meanwhile, this is easier.  */
+# define setmode _setmode
+int _setmode (int, int);
+#define HAVE_SETMODE 1
+#endif
 
 /* output_stream()-- Return a stream pointer to the default output stream.
  * Called on initialization. */
@@ -1057,10 +1333,10 @@
   stream * s;
 
 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
-  setmode (STDOUT_FILENO, O_BINARY);
+  setmode (GFC_STDOUT_FILENO, O_BINARY);
 #endif
 
-  s = fd_to_stream (STDOUT_FILENO, PROT_WRITE);
+  s = fd_to_stream (GFC_STDOUT_FILENO, PROT_WRITE);
   return s;
 }
 
@@ -1074,10 +1350,10 @@
   stream * s;
 
 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
-  setmode (STDERR_FILENO, O_BINARY);
+  setmode (GFC_STDERR_FILENO, O_BINARY);
 #endif
 
-  s = fd_to_stream (STDERR_FILENO, PROT_WRITE);
+  s = fd_to_stream (GFC_STDERR_FILENO, PROT_WRITE);
   return s;
 }
 
@@ -1098,7 +1374,7 @@
   int written;
   int fd;
 
-  fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
+  fd = options.use_stderr ? GFC_STDERR_FILENO : GFC_STDOUT_FILENO;
 #ifdef HAVE_VSNPRINTF
   written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
 #else
@@ -1365,7 +1641,11 @@
 
   if (unpack_filename (path, u->file, u->file_len))
     {				/* Shouldn't be possible */
+#ifndef __MINGW32CE__
       errno = ENOENT;
+#else
+      SetLastError (ERROR_FILE_NOT_FOUND);
+#endif
       return 1;
     }
 
@@ -1495,10 +1775,11 @@
 static int
 fallback_access (const char *path, int mode)
 {
-  if ((mode & R_OK) && open (path, O_RDONLY) < 0)
+  /* Values < -1 are forbidden by POSIX but indicate success on Windows CE.  */
+  if ((mode & R_OK) && open (path, O_RDONLY) == -1)
     return -1;
 
-  if ((mode & W_OK) && open (path, O_WRONLY) < 0)
+  if ((mode & W_OK) && open (path, O_WRONLY) == -1)
     return -1;
 
   return 0;
@@ -1596,7 +1877,13 @@
 int
 stream_isatty (stream *s)
 {
+#ifdef __MINGW32CE__
+  return (((unix_stream *) s)->fd == GFC_STDIN_FILENO
+	  || ((unix_stream *) s)->fd == GFC_STDOUT_FILENO
+	  || ((unix_stream *) s)->fd == GFC_STDERR_FILENO);
+#else
   return isatty (((unix_stream *) s)->fd);
+#endif
 }
 
 char *
diff -Naur a/src/libgfortran/io/write.c b/src/libgfortran/io/write.c
--- a/src/libgfortran/io/write.c	2009-10-12 21:22:25.000000000 +0300
+++ b/src/libgfortran/io/write.c	2010-03-30 10:40:35.000000000 +0300
@@ -31,7 +31,9 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #define star_fill(p, n) memset(p, '*', n)
 
 #include "write_float.def"
@@ -325,7 +327,7 @@
 		}
 
 	      /* Write out the CR_LF sequence.  */ 
-	      write_default_char4 (dtp, crlf, 2, 0);
+	      write_default_char4 (dtp, (gfc_char4_t *) crlf, 2, 0);
 	    }
 	  else
 	    bytes++;
diff -Naur a/src/libgfortran/io/write_float.def b/src/libgfortran/io/write_float.def
--- a/src/libgfortran/io/write_float.def	2009-10-12 21:22:25.000000000 +0300
+++ b/src/libgfortran/io/write_float.def	2010-03-30 10:40:35.000000000 +0300
@@ -752,6 +752,11 @@
 
 #endif
 
+#if defined (__MINGW32CE__) && !defined (signbit)
+/* Should use __builtin_signbit on all targets? */
+# define signbit(x) __builtin_signbit (x)
+#endif
+
 #define WRITE_FLOAT(x,y)\
 {\
 	GFC_REAL_ ## x tmp;\
diff -Naur a/src/libgfortran/libgfortran.h b/src/libgfortran/libgfortran.h
--- a/src/libgfortran/libgfortran.h	2009-10-12 21:22:26.000000000 +0300
+++ b/src/libgfortran/libgfortran.h	2010-03-30 10:40:36.000000000 +0300
@@ -659,6 +659,12 @@
 extern const char *get_oserror (void);
 internal_proto(get_oserror);
 
+extern GFC_INTEGER_4 get_oserrno (void);
+internal_proto(get_oserrno);
+
+extern void clear_oserrno (void);
+internal_proto(clear_oserrno);
+
 extern const char *translate_error (int);
 internal_proto(translate_error);
 
diff -Naur a/src/libgfortran/runtime/environ.c b/src/libgfortran/runtime/environ.c
--- a/src/libgfortran/runtime/environ.c	2009-10-12 21:22:17.000000000 +0300
+++ b/src/libgfortran/runtime/environ.c	2010-03-30 10:40:31.000000000 +0300
@@ -41,6 +41,15 @@
 
 options_t options;
 
+#ifdef __MINGW32CE__
+/* No environ on CE.  Force all defaults.  */
+static char *
+ce_getenv (const char *name __attribute ((unused)))
+{
+  return NULL;
+}
+#define getenv ce_getenv
+#endif
 
 typedef struct variable
 {
diff -Naur a/src/libgfortran/runtime/error.c b/src/libgfortran/runtime/error.c
--- a/src/libgfortran/runtime/error.c	2009-10-12 21:22:17.000000000 +0300
+++ b/src/libgfortran/runtime/error.c	2010-03-30 10:40:31.000000000 +0300
@@ -27,7 +27,6 @@
 #include "libgfortran.h"
 #include <assert.h>
 #include <string.h>
-#include <errno.h>
 
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
@@ -398,7 +397,7 @@
 
   /* Set the error status.  */
   if ((cmp->flags & IOPARM_HAS_IOSTAT))
-    *cmp->iostat = (family == LIBERROR_OS) ? errno : family;
+    *cmp->iostat = (family == LIBERROR_OS) ? get_oserrno () : family;
 
   if (message == NULL)
     message =
diff -Naur a/src/libgfortran/runtime/main.c b/src/libgfortran/runtime/main.c
--- a/src/libgfortran/runtime/main.c	2009-10-12 21:22:17.000000000 +0300
+++ b/src/libgfortran/runtime/main.c	2010-03-30 10:40:31.000000000 +0300
@@ -104,7 +104,8 @@
 #define DIR_SEPARATOR '/'
 #endif
 
-  char buf[PATH_MAX], *cwd, *path;
+  char buf[PATH_MAX], *path;
+  const char *cwd;
 
   /* On the simulator argv is not set.  */
   if (argv0 == NULL || argv0[0] == '/')
diff -Naur a/src/libiberty/cygpath.c b/src/libiberty/cygpath.c
--- a/src/libiberty/cygpath.c	2009-10-12 21:22:38.000000000 +0300
+++ b/src/libiberty/cygpath.c	2010-03-30 10:40:44.000000000 +0300
@@ -218,6 +218,13 @@
 		  cygpath_initialized = 0;
 		  goto retry;
 		}
+	      else
+		{
+		  /* Give up, but in case the error is specific to
+		     this path, reopen at the next request.  */
+		  cygpath_close ();
+		  cygpath_initialized = 0;
+		}
 	    }
 	  goto error;
 	}
@@ -249,18 +256,66 @@
   return false;
 }
 
+typedef struct
+{
+  DWORD dwRVAFunctionNameList;
+  DWORD dwUseless1;
+  DWORD dwUseless2;
+  DWORD dwRVAModuleName;
+  DWORD dwRVAFunctionAddressList;
+} IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY;
+
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
+
 /* Returns the handle for the MVCRT DLL, or NULL if it is not
    available.  */
 static HMODULE
 msvcrt_dll (void)
 {
   static HMODULE dll = (HMODULE)(-1);
+  PIMAGE_OPTIONAL_HEADER opth;
+  PIMAGE_IMPORT_MODULE_DIRECTORY impdir;
+  HANDLE image;
+
+  /* After we call GetModuleHandle, DLL will be either a valid handle
+     or NULL, so this check ensures that we only try to load the
+     library once.  */
+  if (dll != (HMODULE)(-1))
+    return dll;
+
+  dll = NULL;
+
+  /* Check which C runtime is loaded by this executable.  Do that by
+     looking at the import directory for DLLs the EXE links to that
+     looks like msvcr*.  This catches e.g., `msvcr90.dll' and
+     `msvcrt.dll'.  */
+
+  image = GetModuleHandle (NULL);
+
+  /* Get to the PE optional header.  */
+  opth = (PIMAGE_OPTIONAL_HEADER)
+    ((DWORD) image + ((PIMAGE_DOS_HEADER) image)->e_lfanew
+     + sizeof (DWORD) + sizeof (IMAGE_FILE_HEADER));
+  impdir = (PIMAGE_IMPORT_MODULE_DIRECTORY)
+    (opth->ImageBase
+     + opth->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
 
-  /* After we call LoadLibrary, DLL will be either a valid handle or
-     NULL, so this check ensures that we only try to load the library
-     once.  */
-  if (dll == (HMODULE)(-1))
-    dll = LoadLibrary ("msvcrt.dll");
+  for (; impdir->dwRVAModuleName; impdir++)
+    {
+      char *dllname;
+
+      dllname = (char *) opth->ImageBase + impdir->dwRVAModuleName;
+      if (strncasecmp (dllname, "msvcr", sizeof ("msvcr") - 1) == 0)
+	{
+	  dll = GetModuleHandle (dllname);
+	  if (dll == NULL)
+	    {
+	      if (cygpath_log)
+		cygpath_log_msg ("error: GetModuleHandle failed");
+	    }
+	  break;
+	}
+    }
 
   return dll;
 }
@@ -337,6 +392,44 @@
   return fd;
 }
 
+/* Call the underlying MSVCRT stat with PATH and MODE, and return
+   what it returns.  */
+int
+msvcrt_stat (const char *path, struct stat *buffer)
+{
+  typedef int *(stat_type)(const char *path,
+			   struct stat *buffer);
+
+  static stat_type *f = NULL;
+
+  /* Get the address of "stat".  */
+  if (!f)
+    {
+      HMODULE dll = msvcrt_dll ();
+      if (!dll)
+	{
+	  errno = ENOSYS;
+	  return NULL;
+	}
+      if (sizeof (time_t) == 8)
+	f = (stat_type *) GetProcAddress (dll, "_stat64i32");
+      else
+	{
+	  f = (stat_type *) GetProcAddress (dll, "_stat32");
+	  if (!f)
+	    f = (stat_type *) GetProcAddress (dll, "_stat");
+	}
+      if (!f)
+	{
+	  errno = ENOSYS;
+	  return NULL;
+	}
+    }
+
+  /* Call fopen.  */
+  return (*f)(path, buffer);
+}
+
 int
 stat (const char *path, struct stat *buffer)
 {
@@ -344,12 +437,12 @@
   char win32_path[MAX_PATH + 1];
 
   /* Assume PATH is a Windows path.  */
-  r = _stat (path, (struct _stat *) buffer);
+  r = msvcrt_stat (path, (struct _stat *) buffer);
   if (r != -1 || errno != ENOENT)
     return r;
   /* Perhaps it is a Cygwin path?  */
   if (cygpath (path, win32_path))
-    r = _stat (win32_path, (struct _stat *) buffer);
+    r = msvcrt_stat (win32_path, (struct _stat *) buffer);
   return r;
 }
 
diff -Naur a/src/libiberty/pex-common.c b/src/libiberty/pex-common.c
--- a/src/libiberty/pex-common.c	2009-10-12 21:22:38.000000000 +0300
+++ b/src/libiberty/pex-common.c	2010-03-30 10:40:44.000000000 +0300
@@ -505,6 +505,7 @@
   if (o < 0 || o == STDIN_FILE_NO)
     return NULL;
   obj->read_err = obj->funcs->fdopenr (obj, o, binary);
+  obj->stderr_pipe = -1;
   return obj->read_err;    
 }
 
@@ -597,8 +598,17 @@
 void
 pex_free (struct pex_obj *obj)
 {
+  /* Close pipe file descriptors corresponding to child's stdout and
+     stderr so that the child does not hang trying to output anything
+     while we're waiting for it.  */
   if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
     obj->funcs->close (obj, obj->next_input);
+  if (obj->stderr_pipe >= 0 && obj->stderr_pipe != STDIN_FILE_NO)
+    obj->funcs->close (obj, obj->stderr_pipe);
+  if (obj->read_output != NULL)
+    fclose (obj->read_output);
+  if (obj->read_err != NULL)
+    fclose (obj->read_err);
 
   /* If the caller forgot to wait for the children, we do it here, to
      avoid zombies.  */
@@ -619,10 +629,6 @@
     free (obj->status);
   if (obj->time != NULL)
     free (obj->time);
-  if (obj->read_output != NULL)
-    fclose (obj->read_output);
-  if (obj->read_err != NULL)
-    fclose (obj->read_err);
 
   if (obj->remove_count > 0)
     {
diff -Naur a/src/libstdc++-v3/config/os/nucleus/arm-eabi-extra.ver b/src/libstdc++-v3/config/os/nucleus/arm-eabi-extra.ver
--- a/src/libstdc++-v3/config/os/nucleus/arm-eabi-extra.ver	1970-01-01 02:00:00.000000000 +0200
+++ b/src/libstdc++-v3/config/os/nucleus/arm-eabi-extra.ver	2010-03-30 10:40:24.000000000 +0300
@@ -0,0 +1,18 @@
+# Appended to version file.
+
+CXXABI_ARM_1.3.3 {
+   # ARM ABI helper functions provided in libsupc++.
+   __aeabi_atexit;
+   __aeabi_vec_ctor_nocookie_nodtor;
+   __aeabi_vec_ctor_cookie_nodtor;
+   __aeabi_vec_cctor_nocookie_nodtor;
+   __aeabi_vec_new_cookie_noctor;
+   __aeabi_vec_new_nocookie;
+   __aeabi_vec_new_cookie_nodtor;
+   __aeabi_vec_new_cookie;
+   __aeabi_vec_dtor;
+   __aeabi_vec_dtor_cookie;
+   __aeabi_vec_delete;
+   __aeabi_vec_delete3;
+   __aeabi_vec_delete3_nodtor;
+};
diff -Naur a/src/libstdc++-v3/configure b/src/libstdc++-v3/configure
--- a/src/libstdc++-v3/configure	2009-10-12 21:22:15.000000000 +0300
+++ b/src/libstdc++-v3/configure	2010-03-30 10:40:28.000000000 +0300
@@ -4969,6 +4969,10 @@
   lt_cv_file_magic_cmd='$OBJDUMP -f'
   ;;
 
+nucleuseabi*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
 darwin* | rhapsody*)
   lt_cv_deplibs_check_method=pass_all
   ;;
@@ -5730,7 +5734,7 @@
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5733 "configure"' > conftest.$ac_ext
+  echo '#line 5737 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7876,11 +7880,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7879: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7883: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7883: \$? = $ac_status" >&5
+   echo "$as_me:7887: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8215,11 +8219,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8218: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8222: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8222: \$? = $ac_status" >&5
+   echo "$as_me:8226: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8320,11 +8324,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8323: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8327: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8327: \$? = $ac_status" >&5
+   echo "$as_me:8331: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8375,11 +8379,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8378: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8382: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8382: \$? = $ac_status" >&5
+   echo "$as_me:8386: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -10294,6 +10298,21 @@
   shlibpath_overrides_runpath=yes
   ;;
 
+nucleus*)
+  case $host_vendor in
+    samsung)
+      version_type=linux
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+      soname_spec='$libname${shared_ext}$major'
+      shlibpath_var=LD_LIBRARY_PATH
+      hardcode_into_libs=yes
+      ;;
+    *)
+      dynamic_linker=no
+      ;;
+  esac
+  ;;
+
 *nto* | *qnx*)
   version_type=qnx
   need_lib_prefix=no
@@ -11242,7 +11261,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11245 "configure"
+#line 11264 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11338,7 +11357,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11341 "configure"
+#line 11360 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13364,11 +13383,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13367: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13386: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13371: \$? = $ac_status" >&5
+   echo "$as_me:13390: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13463,11 +13482,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13466: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13485: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13470: \$? = $ac_status" >&5
+   echo "$as_me:13489: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -13515,11 +13534,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13518: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13537: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13522: \$? = $ac_status" >&5
+   echo "$as_me:13541: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -14220,6 +14239,21 @@
   shlibpath_overrides_runpath=yes
   ;;
 
+nucleus*)
+  case $host_vendor in
+    samsung)
+      version_type=linux
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+      soname_spec='$libname${shared_ext}$major'
+      shlibpath_var=LD_LIBRARY_PATH
+      hardcode_into_libs=yes
+      ;;
+    *)
+      dynamic_linker=no
+      ;;
+  esac
+  ;;
+
 *nto* | *qnx*)
   version_type=qnx
   need_lib_prefix=no
@@ -14592,7 +14626,7 @@
     #
     # Fake what AC_TRY_COMPILE does.  XXX Look at redoing this new-style.
     cat > conftest.$ac_ext << EOF
-#line 14595 "configure"
+#line 14629 "configure"
 struct S { ~S(); };
 void bar();
 void foo()
@@ -14764,7 +14798,7 @@
   # unnecessary for a builtins test.
 
     cat > conftest.$ac_ext << EOF
-#line 14767 "configure"
+#line 14801 "configure"
 int main()
 {
   typedef bool atomic_type;
@@ -14803,7 +14837,7 @@
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 14806 "configure"
+#line 14840 "configure"
 int main()
 {
   typedef short atomic_type;
@@ -14842,7 +14876,7 @@
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 14845 "configure"
+#line 14879 "configure"
 int main()
 {
   // NB: _Atomic_word not necessarily int.
@@ -14882,7 +14916,7 @@
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 14885 "configure"
+#line 14919 "configure"
 int main()
 {
   typedef long long atomic_type;
diff -Naur a/src/libstdc++-v3/configure.host b/src/libstdc++-v3/configure.host
--- a/src/libstdc++-v3/configure.host	2009-10-12 21:22:15.000000000 +0300
+++ b/src/libstdc++-v3/configure.host	2010-03-30 10:40:28.000000000 +0300
@@ -317,6 +317,9 @@
 	;;
     esac
     ;;
+  arm*-*-nucleuseabi)
+    port_specific_symbol_files="\$(srcdir)/../config/os/nucleus/arm-eabi-extra.ver"
+    ;;
   powerpc*-*-darwin*)
     port_specific_symbol_files="\$(srcdir)/../config/os/bsd/darwin/ppc-extra.ver"
     ;;
diff -Naur a/src/libstdc++-v3/libsupc++/eh_personality.cc b/src/libstdc++-v3/libsupc++/eh_personality.cc
--- a/src/libstdc++-v3/libsupc++/eh_personality.cc	2009-10-12 21:21:20.000000000 +0300
+++ b/src/libstdc++-v3/libsupc++/eh_personality.cc	2010-03-30 10:39:59.000000000 +0300
@@ -392,6 +392,8 @@
   switch (state & _US_ACTION_MASK)
     {
     case _US_VIRTUAL_UNWIND_FRAME:
+      if (state & _US_FORCE_UNWIND)
+	CONTINUE_UNWINDING;
       actions = _UA_SEARCH_PHASE;
       break;
 
diff -Naur a/src/libstdc++-v3/libsupc++/Makefile.am b/src/libstdc++-v3/libsupc++/Makefile.am
--- a/src/libstdc++-v3/libsupc++/Makefile.am	2009-10-12 21:21:20.000000000 +0300
+++ b/src/libstdc++-v3/libsupc++/Makefile.am	2010-03-30 10:39:59.000000000 +0300
@@ -32,7 +32,7 @@
 
 if LIBSUPCXX_PRONLY
 sources = \
-	eh_personality.cc
+	eh_personality.cc vec.cc
 
 else
 
diff -Naur a/src/libstdc++-v3/libsupc++/Makefile.in b/src/libstdc++-v3/libsupc++/Makefile.in
--- a/src/libstdc++-v3/libsupc++/Makefile.in	2009-10-12 21:21:20.000000000 +0300
+++ b/src/libstdc++-v3/libsupc++/Makefile.in	2010-03-30 10:39:59.000000000 +0300
@@ -107,7 +107,7 @@
 @LIBSUPCXX_PRONLY_FALSE@	si_class_type_info.lo tinfo.lo \
 @LIBSUPCXX_PRONLY_FALSE@	tinfo2.lo vec.lo \
 @LIBSUPCXX_PRONLY_FALSE@	vmi_class_type_info.lo vterminate.lo
-@LIBSUPCXX_PRONLY_TRUE@am__objects_1 = eh_personality.lo
+@LIBSUPCXX_PRONLY_TRUE@am__objects_1 = eh_personality.lo vec.lo
 @GLIBCXX_HOSTED_TRUE@@LIBSUPCXX_PRONLY_FALSE@am__objects_2 =  \
 @GLIBCXX_HOSTED_TRUE@@LIBSUPCXX_PRONLY_FALSE@	cp-demangle.lo
 am_libsupc___la_OBJECTS = $(am__objects_1) $(am__objects_2)
@@ -426,7 +426,7 @@
 @LIBSUPCXX_PRONLY_FALSE@	vterminate.cc
 
 @LIBSUPCXX_PRONLY_TRUE@sources = \
-@LIBSUPCXX_PRONLY_TRUE@	eh_personality.cc
+@LIBSUPCXX_PRONLY_TRUE@	eh_personality.cc vec.cc
 
 @LIBSUPCXX_PRONLY_FALSE@headers = \
 @LIBSUPCXX_PRONLY_FALSE@	exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
diff -Naur a/src/libtool.m4 b/src/libtool.m4
--- a/src/libtool.m4	2009-10-12 21:26:07.000000000 +0300
+++ b/src/libtool.m4	2010-03-30 10:42:22.000000000 +0300
@@ -2515,6 +2515,21 @@
   shlibpath_overrides_runpath=yes
   ;;
 
+nucleus*)
+  case $host_vendor in
+    samsung)
+      version_type=linux
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+      soname_spec='$libname${shared_ext}$major'
+      shlibpath_var=LD_LIBRARY_PATH
+      hardcode_into_libs=yes
+      ;;
+    *)
+      dynamic_linker=no
+      ;;
+  esac
+  ;;
+
 *nto* | *qnx*)
   version_type=qnx
   need_lib_prefix=no
@@ -3019,6 +3034,10 @@
   lt_cv_file_magic_cmd='$OBJDUMP -f'
   ;;
 
+nucleuseabi*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
 darwin* | rhapsody*)
   lt_cv_deplibs_check_method=pass_all
   ;;
diff -Naur a/src/release-notes-csl.xml b/src/release-notes-csl.xml
--- a/src/release-notes-csl.xml	2009-10-16 19:19:42.000000000 +0300
+++ b/src/release-notes-csl.xml	2010-04-17 19:19:15.000000000 +0300
@@ -5,6 +5,506 @@
      relevant; it may be removed if it is relevant to all targets.
  -->
 
+      <!-- UUID: 44172080-b495-4eb7-89bf-0cf4bc2a1c1c -->
+      <!-- TARGET: arm-none-eabi arm-none-linux-gnueabi arm-none-symbianelf arm-uclinuxeabi -->
+      <formalpara>
+        <title>ARMv7-A performance improvements</title>
+        <para>
+	  The compiler has been enhanced to produce faster code for the
+	  ARM architecture, particularly for ARMv7-A cores, when compiling
+	  using the <option>-O2</option> option.  This results in a
+	  significant improvement in performance relative to CodeSourcery's
+	  2009q3 releases.
+        </para>
+      </formalpara>
+
+      <!-- UUID: b1bc3def-9358-47ad-bb8f-cffe5da1b485 -->
+      <!-- TARGET: arm-none-eabi arm-none-linux-gnueabi arm-none-symbianelf arm-uclinuxeabi -->
+      <formalpara>
+        <title>Improved code generation for Cortex-A5</title>
+        <para>
+          The compiler has been enhanced to provide instruction
+          scheduling for Cortex-A5 cores.  To take advantage of this,
+          use the <option>-mcpu=cortex-a5</option> command-line option.
+        </para>
+      </formalpara>
+
+      <!-- UUID: b717d668-393f-4984-ae23-052eb6102560 -->
+      <!-- TARGET: mips*-sde* -->
+      <formalpara>
+        <title>Optimized software floating-point routines</title>
+        <para>
+	  The software floating-point emulation routines used by GCC when
+	  linking with <option>-msoft-float</option> have been updated.
+	  The new routines provide significant speed increases.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 918e787b-d63d-4611-b7af-e114084a1164 -->
+      <!-- TARGET: sh* -->
+      <formalpara>
+        <title>Internal compiler error fix</title>
+        <para>
+          A bug has been fixed that caused the compiler to crash
+	  when compiling code using a large constant in a conditional
+	  expression at <option>-O2</option> or higher
+	  optimization levels.
+        </para>
+      </formalpara>
+
+      <!-- UUID: f760b0ab-41cf-41d7-a2e0-6f6eadebf855 -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>C++ array initializer optimization</title>
+        <para>
+          The compiler now generates better code for some
+	  non-constant array initializations in C++.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 8ead0635-77b8-4af7-86bb-c5d35e9acfcf -->
+      <!-- TARGET: arm* -->
+      <formalpara features="armfloat">
+        <title>GCC inline assembly bug fixes</title>
+        <para>
+          A bug that caused NEON/VFP registers specified in the
+	  clobber list of inline assembly statements to be saved
+	  and restored incorrectly has been fixed.  Another bug
+	  that caused incorrect code when double-precision or
+	  quad-precision registers were specified in the clobber
+	  list has also been fixed.
+        </para>
+      </formalpara>
+
+      <!-- UUID: d254cbf2-fe8e-4d9c-abaf-094946d2cce3 -->
+      <!-- TARGET: arm-none-eabi arm-none-linux-gnueabi arm-none-symbianelf arm-uclinuxeabi -->
+      <formalpara>
+        <title>Better use of NEON instructions on Cortex-A8</title>
+        <para>
+	  The compiler now generates better code when optimizing for the
+	  Cortex-A8 by being less eager to use NEON instructions.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 7c04f8ce-3419-4e1b-99b9-e6d1d0a588bd -->
+      <!-- TARGET: arm-none-eabi arm-none-linux-gnueabi arm-none-symbianelf arm-uclinuxeabi -->
+      <formalpara>
+        <title>Optimization of ARM NEON
+	<function>vdupq_n*</function> intrinsics</title>
+        <para>
+          The compiler now generates better code for
+	  <function>vdupq_n*</function> intrinsics to load
+	  particular constants.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 293be974-3da3-432c-b1da-e21b95b26f3e -->
+      <!-- TARGET: * -->
+      <formalpara>
+	<title>Improved code generation for <literal>if</literal> statements</title>
+	<para>
+	  The compiler can now generate better code for <literal>if</literal>
+	  statements when the then and else clauses contain similar code.
+	</para>
+      </formalpara>
+
+      <!-- UUID: 1088a2da-f08c-480c-823a-1596f9ef5518 -->
+      <!-- TARGET: powerpc-linux-gnu powerpc-eabi -->
+      <formalpara>
+        <title>Optimized E500 software floating-point functions</title>
+        <para>
+          &csl_prod; now provides double-precision floating-point
+          arithmetic libraries that are optimized for Freescale CPUs
+          containing E500 cores, such as the 8540 and the 8548.  To use
+          the optimized libraries in your application, link
+          with <option>-te500v1</option> or <option>-te500v2</option>.
+        </para>
+      </formalpara>
+
+       <!-- UUID: f5873792-76f0-477a-a3fe-da42c82823d3 -->
+      <!-- TARGET: * -->
+      <formalpara>
+        <title>
+	GCC internal compiler error with <code>optimize</code> attribute</title>
+        <para>
+          A bug has been fixed that caused the compiler to crash
+	  when invoked with the <option>-O0</option> or
+	  <option>-O1</option> option on code using the
+	  <code>optimize</code> attribute to specify higher
+	  optimization levels for individual functions. 
+        </para>
+      </formalpara>
+
+      <!-- UUID: 5559e24f-e51e-4b63-8bb9-56bf903d0b7b -->
+      <!-- TARGET: powerpc-* -->
+      <formalpara>
+        <title>IBM PowerPC 476 support</title>
+        <para>
+          &csl_sgxx; now includes support for IBM PowerPC 476
+          processors.  To compile for these processors,
+          use <option>-mcpu=476fp</option> for processors with
+          hardware floating-point support
+          and <option>-mcpu=476</option> for processors without
+          hardware floating-point support.
+        </para>
+      </formalpara>
+
+      <!-- UUID: fe6124be-8302-41dd-9d45-f404685398b5 -->
+      <!-- TARGET: powerpc-* -->
+      <formalpara>
+        <title>Internal compiler error fix</title>
+        <para>
+          A bug has been fixed that caused the compiler to crash after
+          issuing a warning
+          <literal>function called through a non-compatible type</literal>.
+          Such code has undefined behavior at runtime, but the
+          compiler no longer crashes while processing it.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 769eba71-5d62-4e77-a011-036d52a8edbb -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>ARM internal compiler error fix</title>
+        <para>
+          A bug that caused the error <literal>internal compiler error:
+	  in get_arm_condition_code</literal> when compiling code using
+	  64-bit integers has been fixed.
+        </para>
+      </formalpara>
+
+      <!-- UUID: da1abca5-0f09-4a6f-8a0a-3ce81590a309 -->
+      <!-- TARGET: * -->
+      <formalpara>
+        <title>GCC internal compiler error</title>
+        <para>
+          A bug has been fixed that caused GCC to crash when
+	  compiling some C++ code using templates at
+	  <option>-O2</option> or <option>-O3</option>.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 06169b75-2491-4edb-8a61-48e1af722965 -->
+      <!-- TARGET: arm* -->
+      <formalpara features="armfloat">
+        <title>Improved NEON code generation for 0.0 constants</title>
+        <para>
+          The compiler now generates better code for loading
+	  double float 0.0 constants on processors supporting
+	  NEON instructions.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 0fbcfecd-db20-435c-abfe-115bd75a807b -->
+      <!-- TARGET: mips* -->
+      <formalpara>
+        <title>Incorrect code generation bug fix</title>
+        <para>
+          A bug in GCC has been fixed that resulted in incorrect
+	  code for some <type>unsigned short</type> array accesses
+	  when compiling with <option>-mdsp</option>.
+        </para>
+      </formalpara>
+
+      <!-- UUID: dac2960f-f739-4dc6-86d3-8105d8d0749f -->
+      <!-- TARGET: * -->
+      <formalpara>
+        <title>Debugging preprocessed source code</title>
+        <para>
+          A compiler bug has been fixed that caused debug output to
+	  erroneously contain the name of the intermediate
+	  preprocessed file.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 9b64a00e-21d1-416b-b15f-4087c398c021 -->
+      <!-- TARGET: arm-none-eabi arm-uclinuxeabi -->
+      <formalpara>
+        <title>Support for ARM Cortex-M4 cores</title>
+        <para>
+	  &csl_sgxx; now includes support for ARM Cortex-M4 cores.
+	  Use the <option>-mcpu=cortex-m4</option> command-line option.
+        </para>
+      </formalpara>
+
+      <!-- UUID: ec0b2564-7646-4658-9ec8-4e42df3c72f2 -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>Thumb-2 size optimization improvements</title>
+        <para>
+          The compiler has been enhanced to produce smaller code for the
+          ARM architecture, particularly for Thumb-2 mode, when compiling
+          using the <option>-Os</option> option.  This results in a
+          significant improvement in code size relative to CodeSourcery's
+          2009q3 releases.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 1ce4c511-f492-4df8-ab4a-ffd3f43a0cb2 -->
+      <!-- TARGET: powerpc* -->
+      <formalpara>
+        <title><option>-mblock-move-inline-limit</option> option added</title>
+        <para>
+          The compiler now supports
+          the <option>-mblock-move-inline-limit</option> option.  This
+          option enables you to specify the maximum size of block moves
+          (such as calls to <function>memcpy</function> or structure
+          copies) that should be inlined.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 988524cf-4405-49a9-81bf-4aef762939ff -->
+      <!-- TARGET: powerpc* -->
+      <formalpara>
+        <title>Improved use of <literal>isel</literal> instruction</title>
+        <para>
+          When compiling for Freescale's E500 and QorIQ processors, the
+          compiler now uses the <literal>isel</literal> instruction in
+          sequences where the <literal>mfcr</literal> instruction was
+          previously used.  This change permits the compiler to better
+          schedule instructions for improved performance.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 307c288e-ae0c-4431-896a-d3afba7e836e -->
+      <!-- TARGET: mips-linux* -->
+      <formalpara>
+        <title>Default generation of JALS instruction</title>
+        <para>
+	  The compiler now defaults to <option>-mno-jals</option>.
+	  The microMIPS <literal>JALs</literal> instruction is not
+	  compatible with the current implementation of
+	  shared library support in the compiler. 
+        </para>
+      </formalpara>
+
+      <!-- UUID: 6cd552e5-6c61-4304-8383-e63756c48673 -->
+      <!-- TARGET: mips* -->
+      <formalpara>
+	<title>Support for microMIPS instruction encoding</title>
+	<para>
+	  &csl_prod; now supports the microMIPS instruction set
+	  architecture.  To enable microMIPS code generation,
+	  compile and link with <option>-mmicromips</option>.
+	  <phrase components="eclipse_plugin">
+	    In the &csl_sgxx; IDE, select <guilabel>microMIPS</guilabel>
+	    from the <guilabel>Instruction Encoding</guilabel> project
+	    properties option.
+	  </phrase>
+	</para>
+      </formalpara>
+
+      <!-- UUID: 07c22595-2fde-45c6-983e-4befce0308c8 -->
+      <!-- TARGET: mips* -->
+      <formalpara>
+	<title>Support for MIPS M14K and M14Kc processors</title>
+	<para>
+	  &csl_prod; now supports the MIPS M14K and M14Kc processors.
+	  To compile for these targets, use the
+	  <option>-march=m14k -mmicromips</option>
+	  command-line options.
+	  <phrase features="cs3">
+	    Additionally, CS3 board support is provided for the MIPS SEAD-3 LX50 and
+	    LX110 boards which include these processors.
+	    Refer to <xref linkend="chap-cs3"/> for more information about
+	    boards supported by &csl_prod;.
+	  </phrase>
+	</para>
+      </formalpara> 
+
+      <!-- UUID: 4598582c-925e-40cc-b341-c0b5e1bf4597 -->
+      <!-- TARGET: arm-none-eabi arm-none-linux-gnueabi arm-none-symbianelf arm-uclinuxeabi -->
+      <formalpara>
+        <title>Improved code generation for Cortex-A9</title>
+        <para>
+          The compiler has been enhanced to provide better instruction
+          scheduling for Cortex-A9 cores.  To take advantage of this,
+          use the <option>-mcpu=cortex-a9</option> command-line option.
+        </para>
+      </formalpara>
+
+      <!-- UUID: ad0a635b-a2cb-4f84-a095-4f51e4518635 -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>Thumb-2 function call optimization</title>
+        <para>
+          The compiler has been enhanced to generate improved code
+          on Thumb-2 targets for functions that return via calls to
+          other functions.
+        </para>
+      </formalpara>
+
+      <!-- UUID: ec7bcf40-79f3-4994-a226-3fb5c44deff9 -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>Thumb-2 multiply fix</title>
+        <para>
+          A bug that caused an invalid <code>muls</code> instruction
+          to be generated in certain circumstances has been fixed. This
+          affected code compiled for Thumb-2, and resulted in an error
+          from the assembler.
+        </para>
+      </formalpara>
+
+      <!-- UUID: b99bcbfb-8cb0-45c8-9918-f6dca65844dd -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>Thumb-2 internal compiler error fix</title>
+        <para>
+          A bug that caused an internal compiler error when building
+          the QT library for Thumb-2 has been fixed.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 96b09111-8004-4168-8180-adc1a35f7f23 -->
+      <!-- TARGET: powerpc-linux-gnu -->
+      <formalpara>
+        <title>Shorter function prologues with <option>-Os
+        -fPIC</option></title>
+        <para>
+          GCC now generates shorter code sequences for function
+          prologues when compiling with the options <option>-Os
+          -fPIC</option>.  The shorter code sequences enable U-Boot to
+          be compiled successfully.
+        </para>
+      </formalpara>
+
+      <!-- UUID: c6744541-ca9a-4b8b-a64e-a6f2b8abb268 -->
+      <!-- TARGET: arm-none-linux-gnueabi -->
+      <formalpara>
+        <title>Improved <function>backtrace</function> function</title>
+        <para>
+           The <function>backtrace</function> function can now
+           backtrace through C++ exception regions and through
+           functions marked <literal>throw()</literal>.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 0c7d55d7-14ae-4dc6-b17f-1a050e60140a -->
+      <!-- TARGET: arm*-* -->
+      <formalpara>
+        <title>C++ name-mangling of <type>va_list</type></title>
+        <para>
+	  The compiler no longer issues <literal>the mangling of
+	  'va_list' has changed</literal> warnings for references
+	  to <type>std::va_list</type> within system header files.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 463dcbc5-dcae-46f9-b292-8171d3f426c7 -->
+      <!-- TARGET: arm-* -->
+      <formalpara features="armfloat">
+        <title>Improved NEON code generation</title>
+        <para>
+          GCC's code generation for NEON targets
+          (e.g., when compiling with <option>-mfpu=neon</option>)
+          has been improved.
+          In particular, the compiler can now make use of NEON
+          instructions for many 64-bit integer operations.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 9d0c95f1-ca6e-4ef7-b0a2-5e3faf4f511f -->
+      <!-- TARGET: mips*-sde* -->
+      <formalpara>
+        <title>Interrupt handler code generation bug fix</title>
+        <para>
+          A GCC bug has been fixed that caused an assembler warning for
+          some functions marked with the <code>interrupt</code> attribute.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 6d0bfc2d-3b8f-4d56-9193-3866fb8d756d -->
+      <!-- TARGET: m68k* fido* i686* mips* powerpc* sh* sparc* -->
+      <formalpara>
+        <title>Code size with <option>-g</option></title>
+        <para>
+          A bug that caused binary code size regressions in GCC 4.4
+          when compiling with <option>-g</option> has been fixed.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 76a4242b-f5a1-4459-aec5-ae56827885c4 -->
+      <!-- TARGET: arm-none-eabi arm-none-linux-gnueabi arm-none-symbianelf arm-uclinuxeabi -->
+      <formalpara>
+        <title>Indirect function call optimization</title>
+        <para>
+          The instruction sequence used to implement calls via a function
+          pointer has been improved to give better branch-prediction
+          performance on some processors.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 8e14046f-026c-4f51-b4b5-e989bab6e813 -->
+      <!-- TARGET: * -->
+      <formalpara>
+        <title>Optimizer bug fix</title>
+        <para>
+          A bug in GCC that caused internal compiler errors
+          at <option>-O2</option> or above has been fixed.  The bug also
+          occurred at other optimization levels when
+          the <option>-fpromote-loop-indices</option> command-line
+          option was used.
+        </para>
+      </formalpara>
+
+      <!-- UUID: f2c9451d-8510-44a5-ae20-cac085eac270 -->
+      <!-- TARGET: m68k-*uclinux* -->
+      <formalpara>
+        <title><option>-pthread</option> compiler option fix</title>
+        <para>
+          <option>-pthread</option> option now makes GCC include the libpthread
+	  library when invoking the linker.
+        </para>
+      </formalpara>
+
+      <!-- UUID: ff4be5cb-5ed1-4bcb-aa12-77324a333313 -->
+      <!-- TARGET: arm* -->
+      <formalpara>
+        <title>Internal compiler error fix</title>
+        <para>
+	  A bug that caused an internal compiler error when using
+	  <option>-fno-omit-frame-pointer</option> to compile code for Thumb-2
+	  has been fixed.
+        </para>
+      </formalpara>
+
+      <!-- UUID: fe34ce3e-80bb-4c48-8ff0-4258c2d4c395 -->
+      <!-- TARGET: m68k-*linux* -->
+      <formalpara>
+        <title>Tail call optimization bug fix</title>
+        <para>
+          A bug in GCC that caused functions with tail calls to
+          be miscompiled at <option>-O2</option> or above has been
+          fixed.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 1efbb5e2-e011-4277-889c-cfebbee85066 -->
+      <!-- TARGET: arm*-* -->
+      <formalpara>
+        <title>Backtracing through noreturn functions</title>
+        <para>
+	  A compiler bug that made it impossible to obtain a backtrace
+	  through functions declared with the <code>noreturn</code>
+	  attribute has been fixed.  This fix makes it possible for the
+	  debugger to present a useful stack backtrace for applications
+	  that call <function>abort</function>.
+        </para>
+      </formalpara>
+
+      <!-- UUID: 97e78cae-dfe9-4518-9575-a12e1c49ce2a -->
+      <!-- TARGET: sh* -->
+      <formalpara>
+        <title>Thread-local storage in position-independent executables</title>
+        <para>
+          A bug has been fixed that caused internal compiler errors
+          when using the <option>-fpie</option> or
+          <option>-fPIE</option> options to compile programs with
+          thread-local variables.
+        </para>
+      </formalpara>
+
       <!-- UUID: b050825a-db8b-41e9-aa89-2c70ffbf28ab -->
       <!-- TARGET: arm* -->
       <formalpara>
